Implement c++ proxy generator (interface part) 51/170651/15
authorJunghoon Park <jh9216.park@samsung.com>
Fri, 23 Feb 2018 06:00:40 +0000 (15:00 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Fri, 23 Feb 2018 07:28:03 +0000 (07:28 +0000)
Change-Id: Ie47e0196d2e2e87f37b9352b88600c877517faca
Signed-off-by: Junghoon Park <jh9216.park@samsung.com>
idlc/cpp_gen/cpp_gen_base.cc
idlc/cpp_gen/cpp_gen_base.h
idlc/cpp_gen/cpp_gen_base_cb.h [new file with mode: 0644]
idlc/cpp_gen/cpp_proxy_body_gen.cc
idlc/cpp_gen/cpp_proxy_body_gen.h
idlc/cpp_gen/cpp_proxy_body_gen_cb.h [new file with mode: 0644]
idlc/cpp_gen/cpp_proxy_header_gen.cc
idlc/cpp_gen/cpp_proxy_header_gen.h
idlc/cpp_gen/cpp_stub_body_gen.cc
idlc/cpp_gen/cpp_stub_header_gen.cc

index feae307..68f8813 100644 (file)
 
 #include "idlc/cpp_gen/cpp_gen_base.h"
 
+namespace {
+#include "cpp_gen_base_cb.h"
+}
+
 namespace tidl {
 
 CppGeneratorBase::CppGeneratorBase(std::shared_ptr<Document> doc)
@@ -44,49 +48,7 @@ CppGeneratorBase::CppGeneratorBase(std::shared_ptr<Document> doc)
 }
 
 void CppGeneratorBase::GenStructuresForHeader(std::ofstream& stream) {
- const char* cls = R"__cls_bundle(class Bundle final {
- public:
-  Bundle() {
-    raw_ = bundle_create();
-  }
-
-  Bundle(bundle* b) {
-    raw_ = b;
-  }
-
-  ~Bundle() {
-    if (raw_)
-      bundle_free(raw_);
-  }
-
-  Bundle(Bundle&& b) : raw_(b.raw_) {
-    b.raw_ = nullptr;
-  }
-
-  Bundle& operator = (Bundle&& b) {
-    raw_ = b.raw_;
-    b.raw_ = nullptr;
-    return *this;
-  }
-
-  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
-
-  Bundle& operator = (const Bundle& b) {
-    raw_ = bundle_dup(b.GetHandle());
-    return *this;
-  }
-
-  bundle* GetHandle() const {
-    return raw_;
-  }
-
- private:
-  bundle* raw_;
-};
-
-)__cls_bundle";
-
-  stream << cls;
+  stream << CB_BUNDLE;
   for (auto& i : GetDocument().GetBlocks()) {
     if (i->GetType() != Block::TYPE_STRUCTURE)
       continue;
@@ -96,30 +58,14 @@ void CppGeneratorBase::GenStructuresForHeader(std::ofstream& stream) {
   }
 }
 
-void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Structure& st) {
-  std::vector<std::string> p;
-  std::vector<std::string> v;
-  std::vector<std::string> lv;
+void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream,
+                                             const Structure& st) {
   const char ctor[] = "  $$();\n" \
                       "  $$($$);\n";
   const char variable[] = "$$\n";
 
   stream << "class " << st.GetID() << " final ";
 
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().GetMetaType() != nullptr) {
-      lv.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID());
-    }
-    else {
-      if (i->GetType().IsUserDefinedType())
-        p.push_back(i->GetType().ToString() + " " + i->GetID());
-      else
-        p.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID());
-
-      v.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID());
-    }
-  }
-
   GenBrace(stream, 0, [&]() {
     stream << " public:" << NLine(1);
     GenTemplate(ctor, stream,
@@ -131,11 +77,12 @@ void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Struct
       },
       [&]()->std::string {
         std::string str;
-        for (auto& i : p) {
-          str += i;
-
-          if (i != p.back())
+        int n = 1;
+        for (auto& i : st.GetElements().GetElms()) {
+          if (n != 1)
             str += ", ";
+          str += ConvertTypeToString(i->GetType()) + " " + i->GetID();
+          n++;
         }
         return str;
       }
@@ -152,12 +99,12 @@ void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Struct
     GenTemplate(variable, stream,
       [&]()->std::string {
         std::string str;
-        for (auto& i : v) {
-            str += "\n" + Tab(1) + i + "_;";
-        }
-        for (auto& i : lv) {
-            str += "\n" + Tab(1) + i + "_;";
+        for (auto& i : st.GetElements().GetElms()) {
+            str += NLine(1) + Tab(1)
+                + ConvertTypeToString(i->GetType()) + " "
+                + i->GetID() + "_;";
         }
+        str += NLine(1);
         return str;
       }
     );
@@ -241,18 +188,11 @@ void CppGeneratorBase::GenStructureForBody(std::ofstream& stream, const Structur
                       "    : $$ {}";
 
   for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().GetMetaType() == nullptr) {
-      std::pair<std::string, std::string> p;
-      if (i->GetType().IsUserDefinedType()) {
-        p.first = i->GetType().ToString();
-        p.second = i->GetID();
-      }
-      else  {
-        p.first = ConvertTypeToString(i->GetType());
-        p.second = i->GetID();
-      }
-      v.push_back(p);
-    }
+    std::pair<std::string, std::string> p;
+
+    p.first = ConvertTypeToString(i->GetType());
+    p.second = i->GetID();
+    v.push_back(p);
   }
 
   GenTemplate(ctor, stream,
@@ -328,25 +268,9 @@ void CppGeneratorBase::GenSerializer(std::ofstream& stream, const Structure& st,
   stream << " ";
   GenBrace(stream, 0, [&]() {
     for (auto& i : st.GetElements().GetElms()) {
-      if (i->GetType().ToString() == "string") {
-        stream << Tab(1) << "rpc_port_parcel_write_"
-               << parcel_type_map_[i->GetType().ToString()]
-               << "(h, param.Get" << i->GetID() << "().c_str());"
-               << NLine(1);
-      } else if (i->GetType().ToString() == "bundle") {
-        stream << Tab(1) << "rpc_port_parcel_write_bundle(h, param.Get"
-               << i->GetID() << "().GetHandle());" << NLine(1);
-      } else if (i->GetType().GetMetaType() ||
-                 i->GetType().IsUserDefinedType()) {
-        stream << Tab(1) << "h << param.Get" << i->GetID() << "();"
-               << NLine(1);
-      } else {
-        stream << Tab(1) << "rpc_port_parcel_write_"
-               << parcel_type_map_[i->GetType().ToString()]
-               << "(h, param.Get" << i->GetID() << "());"
-               << NLine(1);
-      }
-      stream << NLine(1);
+      stream << AddIndent(TAB_SIZE,
+          ConvertTypeToSerializer(i->GetType(),
+              "param.Get" + i->GetID() + "()", "h"));
     }
     stream << Tab(1) << "return h;" << NLine(1);
   }, false);
@@ -376,43 +300,10 @@ void CppGeneratorBase::GenDeSerializer(std::ofstream& stream,
   stream << " ";
   GenBrace(stream, 0, [&]() {
     for (auto& i : st.GetElements().GetElms()) {
-      if (i->GetType().ToString() == "string") {
-        stream << Tab(1) << "char* " << i->GetID() << " = nullptr;" << NLine(1);
-        stream << Tab(1) << "rpc_port_parcel_read_"
-               << parcel_type_map_[i->GetType().ToString()]
-               << "(h, &" << i->GetID() << ");"
-               << NLine(1);
-        stream << Tab(1) << "param.Set" << i->GetID() << "(" << i->GetID() << ");"
-               << NLine(1);
-        stream << Tab(1) << "free(" << i->GetID() << ");"
-               << NLine(1);
-      } else if (i->GetType().ToString() == "bundle") {
-        stream << Tab(1) << "bundle* " << i->GetID() << " = nullptr;" << NLine(1);
-        stream << Tab(1) << "rpc_port_parcel_read_"
-               << parcel_type_map_[i->GetType().ToString()]
-               << "(h, &" << i->GetID() << ");"
-               << NLine(1);
-        stream << Tab(1) << "param.Set" << i->GetID() << "(Bundle(" << i->GetID() << "));"
-               << NLine(1);
-      } else if (i->GetType().GetMetaType() != nullptr ||
-                 i->GetType().IsUserDefinedType()) {
-        stream << Tab(1) << ConvertTypeToString(i->GetType())
-               << " " << i->GetID() << ";" << NLine(1);
-        stream << Tab(1) << "h >> " << i->GetID() << ";"
-               << NLine(1);
-        stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" << i->GetID() << "));"
-               << NLine(1);
-      } else {
-        stream << Tab(1) << ConvertTypeToString(i->GetType())
-               << " " << i->GetID() << ";" << NLine(1);
-        stream << Tab(1) << "rpc_port_parcel_read_"
-               << parcel_type_map_[i->GetType().ToString()]
-               << "(h, &" << i->GetID() << ");"
-               << NLine(1);
-        stream << Tab(1) << "param.Set" << i->GetID() << "(" << i->GetID() << ");"
-               << NLine(1);
-      }
-      stream << NLine(1);
+      stream << AddIndent(TAB_SIZE,
+          ConvertTypeToDeserializer(i->GetType(), i->GetID(), "h"));
+      stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" << i->GetID() << "));"
+             << NLine(2);
     }
     stream << Tab(1) << "return h;" << NLine(1);
   }, false);
@@ -533,4 +424,339 @@ void CppGeneratorBase::GenListSerializer(std::ofstream& stream, bool proto) {
   }
 }
 
+void CppGeneratorBase::GenMethodId(std::ofstream& stream,
+                                   const Interface& iface) {
+  stream << Tab(1) << "enum class MethodId : int ";
+  GenBrace(stream, TAB_SIZE, [&]() {
+    int cnt = 2;
+    stream << Tab(2) << "Result = 0," << NLine(1);
+    stream << Tab(2) << "Callback = 1," << NLine(1);
+    for (auto& i : iface.GetDeclarations().GetDecls()) {
+      if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+        continue;
+      stream << Tab(2)
+             << i->GetID() << " = " << cnt++ << "," << NLine(1);
+    }
+  }, false, false);
+  stream << ";" << NLine(2);
+}
+
+void CppGeneratorBase::GenDelegateId(std::ofstream& stream,
+                                     const Interface& iface) {
+  stream << Tab(1) << "enum class DelegateId : int ";
+  GenBrace(stream, TAB_SIZE, [&]() {
+    int cnt = 1;
+    for (auto& i : iface.GetDeclarations().GetDecls()) {
+        if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+          continue;
+        stream << Tab(2)
+               << i->GetID() << " = " << cnt++ << "," << NLine(1);
+    }
+  }, false, false);
+  stream << ";" << NLine(2);
+}
+
+void CppGeneratorBase::GenParameters(std::ofstream& stream,
+                                     const Parameters& ps) {
+  bool first = true;
+  for (auto& i : ps.GetParams()) {
+    if (!first) {
+      stream << ", ";
+    }
+
+    std::string ref;
+    auto dir = i->GetParameterType().GetDirection();
+    if (dir == ParameterType::Direction::OUT ||
+        dir == ParameterType::Direction::REF) {
+      ref = "&";
+    }
+
+    stream << ConvertTypeToString(i->GetParameterType().GetBaseType())
+           << ref << " " << i->GetID();
+    first = false;
+  }
+}
+
+void CppGeneratorBase::GenDeclaration(std::ofstream& stream,
+                                     const Interface& iface,
+                                     const Declaration& decl) {
+  stream << ConvertTypeToString(decl.GetType()) << " " << iface.GetID() << "::"
+         << decl.GetID() << "(";
+  GenParameters(stream, decl.GetParameters());
+  stream << ") ";
+}
+
+std::string CppGeneratorBase::ConvertTypeToSerializer(
+    const BaseType& type, std::string id, std::string parcel) {
+  std::string ret;
+
+  if (type.ToString() == "string") {
+    ret += "rpc_port_parcel_write_"
+        + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", " + id + ".c_str());\n";
+  } else if (type.ToString() == "bundle") {
+    ret += "rpc_port_parcel_write_bundle(" + parcel + ", "
+        + id + ".GetHandle());\n";
+  } else if (type.GetMetaType() || type.IsUserDefinedType()) {
+    ret += parcel + " << " + id + ";\n";
+  } else {
+    ret += "rpc_port_parcel_write_"
+        + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", " + id + ");\n";
+  }
+
+  return ret;
+}
+
+std::string CppGeneratorBase::ConvertTypeToDeserializer(
+    const BaseType& type, std::string id, std::string parcel,
+    bool make_new_type) {
+  std::string ret;
+
+  if (type.ToString() == "string") {
+    ret += "char* " + id + "_raw  = nullptr;\n";
+    ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", &" + id + "_raw);\n";
+    if (make_new_type) {
+      ret += "std::string " + id + "(" + id + "_raw);\n";
+    } else {
+      ret += id + " = " + id + "_raw;\n";
+    }
+    ret += "free(" + id + "_raw);\n";
+  } else if (type.ToString() == "bundle") {
+    ret += "bundle* " + id + "_raw = nullptr;\n";
+    ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", &" + id + "_raw);\n";
+    if (make_new_type) {
+      ret += "Bundle " + id + "(" + id + "_raw);\n";
+    } else {
+      ret +=  id + " = " + id + "_raw;\n"
+          + "bundle_free(" + id + "_raw);\n";
+    }
+  } else if (type.GetMetaType() != nullptr || type.IsUserDefinedType()) {
+    std::string n;
+
+    if (type.GetMetaType() != nullptr)
+      n = ConvertTypeToString(type);
+    else
+      n = type.ToString();
+
+    if (make_new_type) {
+      ret += n + " ";
+      if (IsDelegateType(type.ToString())) {
+        ret += id + "(port, std::weak_ptr<ServiceBase>(b));\n"
+            + "CallbackBase.";
+      } else {
+        ret += id + ";\n";
+      }
+    }
+    ret += parcel + " >> " + id + ";\n";
+  } else {
+    if (make_new_type)
+      ret += ConvertTypeToString(type) + " " + id + ";\n";
+    ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", &" + id + ");\n";
+  }
+
+  return ret;
+}
+
+void CppGeneratorBase::GenBodyCallbacks(std::ofstream& stream,
+                                   const Interface& iface, bool is_proxy) {
+  GenTemplate(CB_CALLBACK_BASE, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    }
+  );
+
+  for (auto& i : iface.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+          continue;
+    stream << NLine(1);
+    GenBodyCallback(stream, iface, *i, is_proxy);
+  }
+}
+
+void CppGeneratorBase::GenBodyCallback(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl, bool is_proxy) {
+  if (!is_proxy) {
+    const char method[] = "void $$::$$::Invoke()";
+
+    GenTemplate(method, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return decl.GetID();
+      }
+    );
+    GenParameters(stream, decl.GetParameters());
+    stream << ") ";
+    GenBrace(stream, 0, [&]() {
+      //TODO
+
+    }, false);
+  } else {
+    const char cb[] = "void $$::$$::OnReceivedEvent(rpc_port_parcel_h parcel) ";
+
+    GenTemplate(cb, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return decl.GetID();
+      }
+    );
+    GenBrace(stream, 0, [&]() {
+      int cnt = 1;
+      for (auto& i : decl.GetParameters().GetParams()) {
+        std::string v = "param" + std::to_string(cnt);
+        std::string c = ConvertTypeToDeserializer(
+            i->GetParameterType().GetBaseType(), v, "parcel");
+        stream << AddIndent(TAB_SIZE, c) << NLine(1);
+        cnt++;
+      }
+
+      cnt = 1;
+      stream << Tab(1) << "OnReceived(";
+      for (int i = 0; i < decl.GetParameters().GetParams().size(); i++) {
+        if (cnt != 1) {
+          stream << ", ";
+        }
+        stream << "std::move(param" << std::to_string(cnt) << ")";
+        cnt++;
+      }
+      stream << ");" << NLine(1);
+    }, false);
+  }
+}
+
+void CppGeneratorBase::GenHeaderCallbacks(std::ofstream& stream,
+                                          const Interface& iface,
+                                          bool is_proxy) {
+  const char block1[] =
+      "class CallbackBase {\n" \
+      " public:\n" \
+      "  CallbackBase(int delegate_id);\n" \
+      "  virtual ~CallbackBase() = default;\n" \
+      "\n";
+
+  const char block2[] =
+      "  int GetId() const;\n" \
+      "  int GetSeqId() const;\n" \
+      "\n" \
+      " private:\n" \
+      "  friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);\n" \
+      "  friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);\n" \
+      "\n" \
+      "  static int seq_num_;\n" \
+      "  int id_;\n" \
+      "  int seq_id_;\n" \
+      "};\n";
+
+  stream << AddIndent(TAB_SIZE, block1) << NLine(1);
+  if (is_proxy) {
+    stream << Tab(1) << "  virtual void OnReceivedEvent(rpc_port_parcel_h port) = 0;"
+           << NLine(1);
+  }
+  stream << AddIndent(TAB_SIZE, block2) << NLine(1);
+
+  for (auto& i : iface.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+          continue;
+    GenHeaderCallback(stream, *i, is_proxy);
+  }
+}
+
+void CppGeneratorBase::GenHeaderCallback(std::ofstream& stream,
+                                         const Declaration& decl,
+                                         bool is_proxy) {
+  stream << Tab(1) << "class " << decl.GetID()
+         << " : public CallbackBase ";
+  GenBrace(stream, TAB_SIZE, [&]() {
+    const char ctor1[] =
+      "$$(rpc_port_parcel_h port, std::weak_ptr<ServiceBase> service)\n" \
+      "    : CallbackBase(static_cast<int>(DelegateId::$$)) {\n" \
+      "  port_ = port;\n" \
+      "  service_ = std::move(service);\n" \
+      "}\n";
+    const char ctor2[] =
+      "$$()\n" \
+      "    : CallbackBase(static_cast<int>(DelegateId::$$)) {}\n";
+
+    stream << Tab(1) << " public:" << NLine(1);
+    if (!is_proxy) {
+      GenTemplate(AddIndent(TAB_SIZE * 2, ctor1), stream,
+        [&]()->std::string {
+          return decl.GetID();
+        },
+        [&]()->std::string {
+          return decl.GetID();
+        }
+      );
+    } else {
+      GenTemplate(AddIndent(TAB_SIZE * 2, ctor2), stream,
+        [&]()->std::string {
+          return decl.GetID();
+        },
+        [&]()->std::string {
+          return decl.GetID();
+        }
+      );
+    }
+    stream << NLine(1);
+    if (is_proxy) {
+      stream << Tab(2) << "virtual void OnReceived(";
+      GenParameters(stream, decl.GetParameters());
+      stream << ") {}" << NLine(1);
+    } else {
+      stream << Tab(2) << "void Invoke(";
+      GenParameters(stream, decl.GetParameters());
+      stream << ");" << NLine(2);
+    }
+
+    stream << Tab(1) << " private:" << NLine(1);
+    if (is_proxy) {
+      stream << Tab(2) << "void OnReceivedEvent(rpc_port_parcel_h port) override;"
+             << NLine(1);
+    }
+    stream << Tab(2) << "rpc_port_parcel_h port_;" << NLine(1);
+    if (!is_proxy)
+      stream << Tab(2) << "weak_ptr<ServiceBase> service_;" << NLine(1);
+  }, false, false);
+  stream << ";" << NLine(2);
+}
+
+bool CppGeneratorBase::IsDelegateType(const std::string type_name) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+    Interface& iface = static_cast<Interface&>(*i);
+
+    for (auto& j : iface.GetDeclarations().GetDecls()) {
+      if (j->GetMethodType() == Declaration::MethodType::DELEGATE) {
+        if (j->GetID() == type_name)
+          return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 }  // namespace tidl
index 958d9ff..4a5058a 100644 (file)
@@ -38,10 +38,24 @@ class CppGeneratorBase : public Generator {
   void GenDeSerializer(std::ofstream& stream);
   void GenListSerializer(std::ofstream& stream, bool proto = false);
   void GenPrototype(std::ofstream& stream);
-
+  void GenMethodId(std::ofstream& stream, const Interface& iface);
+  void GenDelegateId(std::ofstream& stream, const Interface& iface);
+  void GenParameters(std::ofstream& stream, const Parameters& ps);
+  void GenDeclaration(std::ofstream& stream, const Interface& iface,
+                      const Declaration& decl);
+  void GenBodyCallbacks(std::ofstream& stream, const Interface& iface,
+                        bool is_proxy);
+  void GenHeaderCallbacks(std::ofstream& stream, const Interface& iface,
+                          bool is_proxy);
+  bool IsDelegateType(const std::string type_name);
   std::string ConvertTypeToString(const BaseType& type);
   std::string Tab(int cnt);
   std::string NLine(int cnt);
+  std::string ConvertTypeToDeserializer(const BaseType& type,
+                                        std::string id, std::string parcel,
+                                        bool make_new_type = true);
+  std::string ConvertTypeToSerializer(const BaseType& type,
+                                      std::string id, std::string parcel);
 
  private:
   void GenSetter(std::ofstream& stream, const Element& ele);
@@ -55,6 +69,10 @@ class CppGeneratorBase : public Generator {
                      bool proto = false);
   void GenStructureForHeader(std::ofstream& stream, const Structure& st);
   void GenStructureForBody(std::ofstream& stream, const Structure& st);
+  void GenBodyCallback(std::ofstream& stream, const Interface& iface,
+                       const Declaration& decl, bool is_proxy);
+  void GenHeaderCallback(std::ofstream& stream, const Declaration& decl,
+                         bool is_proxy);
 
  protected:
   const int TAB_SIZE = 2;
diff --git a/idlc/cpp_gen/cpp_gen_base_cb.h b/idlc/cpp_gen/cpp_gen_base_cb.h
new file mode 100644 (file)
index 0000000..602fa75
--- /dev/null
@@ -0,0 +1,74 @@
+const char CB_BUNDLE[] = R"__cls_bundle(class Bundle final {
+ public:
+  Bundle() {
+    raw_ = bundle_create();
+  }
+
+  Bundle(bundle* b) {
+    raw_ = b;
+  }
+
+  ~Bundle() {
+    if (raw_)
+      bundle_free(raw_);
+  }
+
+  Bundle(Bundle&& b) : raw_(b.raw_) {
+    b.raw_ = nullptr;
+  }
+
+  Bundle& operator = (Bundle&& b) {
+    raw_ = b.raw_;
+    b.raw_ = nullptr;
+    return *this;
+  }
+
+  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+  Bundle& operator = (const Bundle& b) {
+    raw_ = bundle_dup(b.GetHandle());
+    return *this;
+  }
+
+  bundle* GetHandle() const {
+    return raw_;
+  }
+
+ private:
+  bundle* raw_;
+};
+
+)__cls_bundle";
+
+const char CB_CALLBACK_BASE[] =
+R"__cpp_cb(
+int $$::CallbackBase::seq_num_ = 0;
+
+$$::CallbackBase::CallbackBase(int delegate_id)
+    : id_(delegate_id) {
+  seq_id_ = seq_num_++;
+}
+
+int $$::CallbackBase::GetId() const {
+  return id_;
+}
+
+int $$::CallbackBase::GetSeqId() const {
+  return seq_id_;
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const $$::CallbackBase& cb) {
+  rpc_port_parcel_write_int32(h, cb.id_);
+  rpc_port_parcel_write_int32(h, cb.seq_id_);
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, $$::CallbackBase& cb) {
+  rpc_port_parcel_read_int32(h, &cb.id_);
+  rpc_port_parcel_read_int32(h, &cb.seq_id_);
+
+  return h;
+}
+
+)__cpp_cb";
\ No newline at end of file
index 823035a..e136bc7 100644 (file)
 
 #include "idlc/cpp_gen/cpp_proxy_body_gen.h"
 
+namespace {
+#include "cpp_proxy_body_gen_cb.h"
+}
+
 namespace tidl {
 
 CppProxyBodyGen::CppProxyBodyGen(std::shared_ptr<Document> doc)
@@ -32,9 +36,6 @@ void CppProxyBodyGen::OnInitGen(std::ofstream& stream) {
   stream << "#include <stdlib.h>" << NLine(1)
          << "#include <assert.h>" << NLine(1)
          <<  NLine(1)
-         << "#include <rpc-port-parcel.h>" << NLine(1)
-         << "#include <rpc-port.h>" << NLine(1)
-         <<  NLine(1)
          << "#include \"" << header_file << "\"" << NLine(2);
   GenNamespace(stream);
 }
@@ -46,21 +47,191 @@ void CppProxyBodyGen::GenNamespace(std::ofstream& stream) {
   stream << "namespace rpc_port ";
   GenBrace(stream, 0, [&]() {
     stream <<  NLine(1);
-    GenPrototype(stream);
     GenStructuresForBody(stream);
-    GenSerializer(stream);
-    GenDeSerializer(stream);
-    GenListSerializer(stream);
     stream << "namespace proxy ";
     GenBrace(stream, 0, [&]() {
-//      GenInterfaces(stream);
+      GenPrototype(stream);
+      GenSerializer(stream);
+      GenDeSerializer(stream);
+      GenListSerializer(stream);
+      GenInterfaces(stream);
     }, false);
   }, false);
 }
 
-void CppProxyBodyGen::GenConstructor(std::ofstream& stream) {
+void CppProxyBodyGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+    Interface& iface = static_cast<Interface&>(*i);
+    GenInterface(stream, iface);
+  }
+}
+
+void CppProxyBodyGen::GenInterface(std::ofstream& stream,
+                                   const Interface& iface) {
+  GenBodyCallbacks(stream, iface, true);
+  GenConstructor(stream, iface);
+  GenDestructor(stream, iface);
+  GenHelperMethods(stream, iface);
+  GenMethods(stream, iface);
+}
+
+void CppProxyBodyGen::GenConstructor(std::ofstream& stream,
+                                     const Interface& iface) {
+  GenTemplate(CB_PROXY_INTERFACE_CTOR, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    }
+  );
+}
+
+void CppProxyBodyGen::GenDestructor(std::ofstream& stream,
+                                    const Interface& iface) {
+  const char cb[] =
+    "$$::~$$() {\n" \
+    " if (proxy_)\n" \
+    "   rpc_port_proxy_destroy(proxy_);\n" \
+    "}\n";
+
+  GenTemplate(cb, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    }
+  );
+}
+
+void CppProxyBodyGen::GenHelperMethods(std::ofstream& stream,
+                                       const Interface& iface) {
+
+  GenTemplate(CB_PROXY_HELPER_METHODS, stream,
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); },
+    [&]()->std::string { return iface.GetID(); }
+  );
+  stream << NLine(1);
+}
+
+void CppProxyBodyGen::GenMethods(std::ofstream& stream,
+                                 const Interface& iface) {
+  auto& decls = iface.GetDeclarations();
 
+  for (auto& i : decls.GetDecls()) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenDeclaration(stream, iface, *i);
+    GenBrace(stream, 0, [&]() {
+      GenInvocation(stream, *i);
+    }, false);
+    stream << NLine(1);
+  }
 }
 
+void CppProxyBodyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
+  const char* pre =
+      "if (port_ == nullptr)\n" \
+      "    throw NotConnectedSocketException();\n" \
+      "\n" \
+      "rpc_port_parcel_h p;\n" \
+      "rpc_port_parcel_create(&p);\n";
+
+  const char* mid =
+      "// Send\n" \
+      "rpc_port_parcel_send(p, port_);\n";
+
+  stream << AddIndent(TAB_SIZE, pre);
+
+  // Serialize
+  stream << Tab(1)
+         << "rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::"
+         << decl.GetID() << "));" << NLine(1);
+  std::string m;
+  std::string l;
+  for (auto& i : decl.GetParameters().GetParams()) {
+    auto& pt = i->GetParameterType();
+    if (pt.GetDirection() == ParameterType::Direction::OUT)
+      continue;
+    m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p");
+    if (IsDelegateType(pt.GetBaseType().ToString()))
+      l += "delegate_list_.emplace_back(new " + pt.GetBaseType().ToString()
+        + "(" + i->GetID() + "));\n";
+  }
+  stream << AddIndent(TAB_SIZE, m) << NLine(1);
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC)
+    stream << Tab(1) << "rpc_port_parcel_h parcel_received;" << NLine(1);
+  stream << Tab(1) << "do ";
+  GenBrace(stream, TAB_SIZE, [&]() {
+    stream << Tab(2) << "std::lock_guard<std::recursive_mutex> lock(mutex_);"
+           << NLine(2);
+    if (!l.empty())
+      stream << AddIndent(TAB_SIZE * 2, l) << NLine(1);
+    stream << AddIndent(TAB_SIZE * 2, mid) << NLine(1);
+    if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
+      stream << Tab(2) << "// Receive" << NLine(1);
+      stream << Tab(2)
+             << "ConsumeCommand(&parcel_received, port_);" << NLine(1);
+    }
+  }, false, false);
+  stream << " while (false);" << NLine(2);
+
+  // Deserialize
+  if (decl.GetMethodType() == Declaration::MethodType::ASYNC) {
+    stream << Tab(1) << "rpc_port_parcel_destroy(p);"
+         << NLine(1);
+    return;
+  }
+
+  const char* receive_block =
+      "if (parcel_received == nullptr) {\n" \
+      "    throw InvalidProtocolException();\n" \
+      "}\n";
+  stream << AddIndent(TAB_SIZE, receive_block) << NLine(1);
+
+  for (auto& i : decl.GetParameters().GetParams()) {
+    if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN) {
+      continue;
+    }
+
+    std::string c = ConvertTypeToDeserializer(
+        i->GetParameterType().GetBaseType(),
+        i->GetID(), "parcel_received", false);
+    if (c != "")
+      stream << AddIndent(TAB_SIZE, c);
+  }
+
+  if (decl.GetType().ToString() != "void") {
+    stream << AddIndent(TAB_SIZE,
+                        ConvertTypeToDeserializer(decl.GetType(),
+                                                "ret", "parcel_received"));
+  }
+
+  stream << Tab(1) << "rpc_port_parcel_destroy(p);"
+         << NLine(1);
+  stream << Tab(1) << "rpc_port_parcel_destroy(parcel_received);"
+         << NLine(1);
+
+  stream << Tab(1) << "return ret;" << NLine(1);
+}
 
 }  // namespace tidl
index eeacd33..0b6c6d4 100644 (file)
@@ -35,8 +35,13 @@ class CppProxyBodyGen : public CppGeneratorBase {
  private:
   void GenNamespace(std::ofstream& stream);
   void GenStructures(std::ofstream& stream);
-  void GenConstructor(std::ofstream& stream);
-  void GenDestructor(std::ofstream& stream);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenConstructor(std::ofstream& stream, const Interface& iface);
+  void GenDestructor(std::ofstream& stream, const Interface& iface);
+  void GenHelperMethods(std::ofstream& stream, const Interface& iface);
+  void GenMethods(std::ofstream& stream, const Interface& iface);
+  void GenInvocation(std::ofstream& stream, const Declaration& decl);
 };
 
 }  // namespace tidl
diff --git a/idlc/cpp_gen/cpp_proxy_body_gen_cb.h b/idlc/cpp_gen/cpp_proxy_body_gen_cb.h
new file mode 100644 (file)
index 0000000..f431f5e
--- /dev/null
@@ -0,0 +1,92 @@
+const char CB_PROXY_HELPER_METHODS[] =
+R"__cpp_cb(
+int $$::Connect() {
+  return rpc_port_proxy_connect(proxy_, target_appid_.c_str(), "$$");
+}
+
+void $$::ProcessReceivedEvent(rpc_port_parcel_h parcel) {
+  int id = 0;
+  int seqId = 0;
+
+  rpc_port_parcel_read_int32(parcel, &id);
+  rpc_port_parcel_read_int32(parcel, &seqId);
+
+  for (auto& i : delegate_list_) {
+    if (i->GetId() == id && i->GetSeqId() == seqId) {
+      i->OnReceivedEvent(parcel);
+      break;
+    }
+  }
+}
+
+void $$::ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port) {
+  do {
+    rpc_port_parcel_h p;
+    int ret = rpc_port_parcel_create_from_port(&p, port);
+    int cmd;
+
+    if (ret != 0)
+      break;
+    rpc_port_parcel_read_int32(p, &cmd);
+    if (cmd == static_cast<int>(MethodId::Result)) {
+      *parcel = p;
+      return;
+    }
+
+    ProcessReceivedEvent(p);
+    rpc_port_parcel_destroy(p);
+    *parcel = nullptr;
+  } while (true);
+  *parcel = nullptr;
+}
+
+void $$::OnConnectedCB(const char *ep, const char *port_name, rpc_port_h port, void *data) {
+  $$* l = static_cast<$$*>(data);
+  l->port_ = port;
+  l->listener_->OnConnected();
+}
+
+void $$::OnDisconnectedCB(const char *ep, const char *port_name, void *data) {
+  $$* l = static_cast<$$*>(data);
+  l->listener_->OnDisconnected();
+}
+
+void $$::OnRejectedCB(const char *ep, const char *port_name, void *data) {
+  $$* l = static_cast<$$*>(data);
+  l->listener_->OnRejected();
+}
+
+void $$::OnReceivedCB(const char *ep, const char *port_name, void *data) {
+  $$* l = static_cast<$$*>(data);
+  int cmd;
+  rpc_port_parcel_h parcel_received;
+
+  do {
+    std::lock_guard<std::recursive_mutex> lock(l->mutex_);
+    if (rpc_port_parcel_create_from_port(&parcel_received, l->port_) != 0)
+      return;
+  } while (false);
+
+  rpc_port_parcel_read_int32(parcel_received, &cmd);
+  if (cmd != static_cast<int>(MethodId::Callback)) {
+    rpc_port_parcel_destroy(parcel_received);
+    throw InvalidProtocolException();
+  }
+
+  l->ProcessReceivedEvent(parcel_received);
+  rpc_port_parcel_destroy(parcel_received);
+}
+)__cpp_cb";
+
+const char CB_PROXY_INTERFACE_CTOR[] =
+R"__cpp_cb(
+$$::$$(IEventListener* listener, const std::string& target_appid)
+    : port_(nullptr), proxy_(nullptr), listener_(listener),
+      target_appid_(target_appid) {
+  rpc_port_proxy_create(&proxy_);
+  rpc_port_proxy_add_connected_event_cb(proxy_, OnConnectedCB, this);
+  rpc_port_proxy_add_disconnected_event_cb(proxy_, OnDisconnectedCB, this);
+  rpc_port_proxy_add_rejected_event_cb(proxy_, OnRejectedCB, this);
+  rpc_port_proxy_add_received_event_cb(proxy_, OnReceivedCB, this);
+}
+)__cpp_cb";
index 761342d..3b30707 100644 (file)
@@ -25,9 +25,13 @@ void CppProxyHeaderGen::OnInitGen(std::ofstream& stream) {
   stream << "#pragma once" << NLine(1)
          <<  NLine(1)
          << "#include <bundle.h>" << NLine(1)
+         << "#include <rpc-port-parcel.h>" << NLine(1)
+         << "#include <rpc-port.h>" << NLine(2)
          <<  NLine(1)
          << "#include <string>" << NLine(1)
          << "#include <vector>" << NLine(1)
+         << "#include <memory>" << NLine(1)
+         << "#include <mutex>" << NLine(1)
          << "#include <list>" << NLine(2);
   GenNamespace(stream);
 }
@@ -42,9 +46,107 @@ void CppProxyHeaderGen::GenNamespace(std::ofstream& stream) {
     GenStructuresForHeader(stream);
     stream << "namespace proxy ";
     GenBrace(stream, 0, [&]() {
-//      GenInterfaces(stream);
+      GenExceptions(stream);
+      GenInterfaces(stream);
     }, false);
   }, false);
 }
 
+void CppProxyHeaderGen::GenExceptions(std::ofstream& stream) {
+  const char cb[] =
+R"__cpp_cb(
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+)__cpp_cb";
+  stream << cb << NLine(1);
+}
+
+void CppProxyHeaderGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+    Interface& iface = static_cast<Interface&>(*i);
+    GenInterface(stream, iface);
+  }
+}
+
+void CppProxyHeaderGen::GenInterface(std::ofstream& stream,
+                                     const Interface& iface) {
+  const char* pub =
+      "class IEventListener {\n" \
+      " public:\n" \
+      "  virtual void OnConnected() = 0;\n" \
+      "  virtual void OnDisconnected() = 0;\n" \
+      "  virtual void OnRejected() = 0;\n" \
+      "};\n"
+      "\n" \
+      "$$(IEventListener* listener, const std::string& target_appid);\n" \
+      "virtual ~$$();\n" \
+      "\n" \
+      "int Connect();\n";
+
+  const char* priv =
+      "static void OnConnectedCB(const char *ep, const char *port_name,\n" \
+      "                          rpc_port_h port, void *data);\n" \
+      "static void OnDisconnectedCB(const char *ep, const char *port_name,\n" \
+      "                             void *data);\n" \
+      "static void OnRejectedCB(const char *ep, const char *port_name, void *data);\n" \
+      "static void OnReceivedCB(const char *ep, const char *port_name, void *data);\n" \
+      "\n" \
+      "rpc_port_h port_;\n" \
+      "rpc_port_proxy_h proxy_;\n" \
+      "IEventListener* listener_;\n" \
+      "std::recursive_mutex mutex_;\n" \
+      "std::list<std::unique_ptr<CallbackBase>> delegate_list_;\n" \
+      "std::string target_appid_;\n";
+
+  stream << NLine(1) << "class " << iface.GetID() << " ";
+  GenBrace(stream, 0, [&]() {
+    stream << " public:" << NLine(1);
+    GenHeaderCallbacks(stream, iface, true);
+    GenTemplate(AddIndent(TAB_SIZE, pub), stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return iface.GetID();
+      }
+    );
+    GenMethods(stream, iface);
+    stream << NLine(1) << " private:" << NLine(1);
+    GenMethodId(stream, iface);
+    GenDelegateId(stream, iface);
+    GenHelperMethods(stream);
+    stream << AddIndent(TAB_SIZE, priv);
+  }, false, false);
+  stream << ";" << NLine(1);
+}
+
+void CppProxyHeaderGen::GenHelperMethods(std::ofstream& stream) {
+  const char* func =
+      "void ProcessReceivedEvent(rpc_port_parcel_h parcel);\n" \
+      "void ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port);\n";
+  stream << AddIndent(TAB_SIZE, func) << NLine(1);
+}
+
+void CppProxyHeaderGen::GenMethods(std::ofstream& stream,
+                                   const Interface& iface) {
+  auto& decls = iface.GetDeclarations();
+
+  for (auto& i : decls.GetDecls()) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenDeclaration(stream, *i);
+  }
+}
+
+void CppProxyHeaderGen::GenDeclaration(std::ofstream& stream,
+                                       const Declaration& decl) {
+  stream << Tab(1) << ConvertTypeToString(decl.GetType()) << " "
+         << decl.GetID() << "(";
+  GenParameters(stream, decl.GetParameters());
+  stream << ");" << NLine(1);
+}
 }  // namespace tidl
index dc4b8df..0e120f8 100644 (file)
@@ -34,6 +34,12 @@ class CppProxyHeaderGen : public CppGeneratorBase {
 
  private:
   void GenNamespace(std::ofstream& stream);
+  void GenExceptions(std::ofstream& stream);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenMethods(std::ofstream& stream, const Interface& iface);
+  void GenDeclaration(std::ofstream& stream, const Declaration& decl);
+  void GenHelperMethods(std::ofstream& stream);
 };
 
 }  // namespace tidl
index c5cc0ca..78399c6 100644 (file)
@@ -32,9 +32,6 @@ void CppStubBodyGen::OnInitGen(std::ofstream& stream) {
   stream << "#include <stdlib.h>" << NLine(1)
          << "#include <assert.h>" << NLine(1)
          <<  NLine(1)
-         << "#include <rpc-port-parcel.h>" << NLine(1)
-         << "#include <rpc-port.h>" << NLine(1)
-         <<  NLine(1)
          << "#include \"" << header_file << "\"" << NLine(2);
   GenNamespace(stream);
 }
index 70996c7..8a36891 100644 (file)
@@ -25,6 +25,8 @@ void CppStubHeaderGen::OnInitGen(std::ofstream& stream) {
   stream << "#pragma once" << NLine(1)
          <<  NLine(1)
          << "#include <bundle.h>" << NLine(1)
+         << "#include <rpc-port-parcel.h>" << NLine(1)
+         << "#include <rpc-port.h>" << NLine(1)
          <<  NLine(1)
          << "#include <string>" << NLine(1)
          << "#include <vector>" << NLine(1)