Generate client-side headers

Test: Ran aidl-cpp
Bug: 23599760
Change-Id: I31ca5be9dd1274ba81ea6a7110e9f2005f86855d
Signed-off-by: Casey Dahlin <sadmac@google.com>
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index d0bd7ba..503e557 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -15,35 +15,56 @@
  */
 
 #include "generate_cpp.h"
+#include "parse_helpers.h"
 
 #include <cctype>
 #include <memory>
 #include <random>
 #include <string>
 
+#include "aidl_language.h"
 #include "ast_cpp.h"
 #include "code_writer.h"
 #include "logging.h"
 
 using std::string;
 using std::unique_ptr;
+using std::vector;
 
 namespace android {
 namespace aidl {
-namespace {
+namespace internals {
 
-const int kGuardSize = 32;
+string StrippedLiteral(const buffer_type& buffer) {
+  std::string i_name = buffer.Literal();
 
-string RandomGuardString() {
-  std::default_random_engine generator;
-  std::uniform_int_distribution<int> distribution(0,25);
+  string c_name;
 
-  string ret{kGuardSize, '-'};
+  if (i_name.length() >= 2 && i_name[0] == 'I' && isupper(i_name[1]))
+    c_name = i_name.substr(1);
+  else
+    c_name = i_name;
 
-  for (char& c : ret)
-    c = 'A' + distribution(generator);
+  return c_name;
+}
 
-  return ret;
+string GetCPPType(type_type *type) {
+  string lit = type->type.Literal();
+
+  if (lit == "int")
+    return "int32_t";
+  else if (lit == "long")
+    return "int64_t";
+  else
+    LOG(FATAL) << "Type not yet supported";
+
+  return "int";
+}
+
+string GetCPPVarDec(type_type* type, string name,
+                    int direction) {
+  return GetCPPType(type) + ((OUT_PARAMETER & direction) ? "* " : " ") +
+      name + type->Brackets();
 }
 
 unique_ptr<CppDocument> BuildClientSource(interface_type* parsed_doc) {
@@ -62,19 +83,75 @@
 }
 
 unique_ptr<CppDocument> BuildClientHeader(interface_type* parsed_doc) {
-  unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
-  return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
+  string i_name = parsed_doc->name.Literal();
+  string c_name = StrippedLiteral(parsed_doc->name);
+  string bp_name = "Bp" + c_name;
+
+  unique_ptr<CppMacroOrConstructorDeclaration> constructor{
+        new CppMacroOrConstructorDeclaration(bp_name, {}, false, false)};
+
+  unique_ptr<CppMacroOrConstructorDeclaration> destructor{
+        new CppMacroOrConstructorDeclaration("~" + bp_name, {}, false, false)};
+
+  vector<unique_ptr<CppDeclaration>> publics;
+  publics.push_back(std::move(constructor));
+  publics.push_back(std::move(destructor));
+
+  for (interface_item_type *item = parsed_doc->interface_items;
+       item;
+       item = item->next) {
+    if (item->item_type != METHOD_TYPE) {
+      LOG(FATAL) << "Unknown interface item type";
+      return nullptr;
+    }
+
+    method_type *m_item = (method_type *)item;
+
+    string method_name = m_item->name.Literal();
+    string return_arg = GetCPPVarDec(&m_item->type, "_aidl_return",
+                                     OUT_PARAMETER);
+
+    vector<string> args;
+
+    for (arg_type *arg = m_item->args; arg; arg = arg->next)
+      args.push_back(GetCPPVarDec(&arg->type, arg->name.Literal(),
+                                  convert_direction(arg->direction.data)));
+
+    args.push_back(return_arg);
+
+    unique_ptr<CppDeclaration> meth {
+        new CppMethodDeclaration("android::status_t", method_name,
+                                 args, false, true)
+    };
+
+    publics.push_back(std::move(meth));
+  }
+
+  unique_ptr<CppClassDeclaration> bp_class{
+      new CppClassDeclaration{bp_name,
+                              "public android::BpInterface<" + i_name + ">",
+                              std::move(publics),
+                              {}
+      }};
+
+  vector<unique_ptr<CppDeclaration>> bp_class_vec;
+  bp_class_vec.push_back(std::move(bp_class));
+
+  unique_ptr<CppNamespace> ns {new CppNamespace{"android", std::move(bp_class_vec)}};
+
+  unique_ptr<CppDocument> bp_header{new CppHeader{bp_name + "_H",
+                                                  {"binder/IBinder.h",
+                                                   "binder/IInterface.h",
+                                                   "utils/Errors.h",
+                                                   i_name + ".h"},
+                                                  std::move(ns) }};
+
+  return bp_header;
 }
 
 unique_ptr<CppDocument> BuildServerHeader(interface_type* parsed_doc) {
-  string i_name = parsed_doc->name.Literal();
-  string c_name;
-
-  if (i_name.length() >= 2 && i_name[0] == 'I' && isupper(i_name[1]))
-    c_name = i_name.substr(1);
-  else
-    c_name = i_name;
-
+  string i_name = parsed_doc->name.Literal();;
+  string c_name = StrippedLiteral(parsed_doc->name);
   string bn_name = "Bn" + c_name;
 
   unique_ptr<CppDeclaration> on_transact{
@@ -100,7 +177,7 @@
 
   unique_ptr<CppNamespace> ns{new CppNamespace{"android", std::move(declarations)}};
 
-  unique_ptr<CppDocument> bn_header{new CppHeader{RandomGuardString(),
+  unique_ptr<CppDocument> bn_header{new CppHeader{bn_name + "_H",
                                                   {"binder/IInterface.h",
                                                    i_name + ".h"},
                                                   std::move(ns) }};
@@ -122,7 +199,9 @@
   return true;
 }
 
-}  // namespace
+}  // namespace internals
+
+using namespace internals;
 
 bool GenerateCpp(const CppOptions& options, interface_type* parsed_doc) {
   bool success = true;