Implement C++ generator for cion 25/265025/8
authorInkyun Kil <inkyun.kil@samsung.com>
Thu, 7 Oct 2021 08:24:45 +0000 (17:24 +0900)
committerInkyun Kil <inkyun.kil@samsung.com>
Thu, 14 Oct 2021 06:08:15 +0000 (15:08 +0900)
Change-Id: Ibce59d9424ad0ccf322c4c0babf9ae9446591098
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
16 files changed:
idlc/gen_cion/cpp_cion_gen_base.cc [new file with mode: 0644]
idlc/gen_cion/cpp_cion_gen_base.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_gen_base_cb.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_proxy_body_gen.cc [new file with mode: 0644]
idlc/gen_cion/cpp_cion_proxy_body_gen.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_proxy_header_gen.cc [new file with mode: 0644]
idlc/gen_cion/cpp_cion_proxy_header_gen.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_stub_body_gen.cc [new file with mode: 0644]
idlc/gen_cion/cpp_cion_stub_body_gen.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_stub_body_gen_cb.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_stub_header_gen.cc [new file with mode: 0644]
idlc/gen_cion/cpp_cion_stub_header_gen.h [new file with mode: 0644]
idlc/gen_cion/cpp_cion_stub_header_gen_cb.h [new file with mode: 0644]
idlc/main.cc

diff --git a/idlc/gen_cion/cpp_cion_gen_base.cc b/idlc/gen_cion/cpp_cion_gen_base.cc
new file mode 100644 (file)
index 0000000..96f428a
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 <ctime>
+#include <vector>
+#include <utility>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+
+namespace {
+#include "idlc/gen_cion/cpp_cion_gen_base_cb.h"
+}
+
+namespace tidl {
+
+CppCionGeneratorBase::CppCionGeneratorBase(std::shared_ptr<Document> doc)
+    : Generator(doc) {
+  type_map_ = {
+      {"char", "char"}, {"int", "int"}, {"short", "short"},
+      {"long", "long long"}, {"string", "std::string"}, {"bool", "bool"},
+      {"list", "std::list"}, {"float", "float"}, {"double", "double"},
+      {"file", "File"}, {"bundle", "Bundle"}, {"void", "void"},
+      {"array", "std::vector"}
+  };
+
+  parcel_type_map_ = {
+    {"char", "byte"},
+    {"int", "int32"},
+    {"short", "int16"},
+    {"long", "int64"},
+    {"string", "string"},
+    {"bool", "bool"},
+    {"float", "float"},
+    {"double", "double"},
+    {"bundle", "bundle"},
+    {"file", "string"},
+  };
+
+  type_init_map_ = {
+    {"char", "0"},
+    {"int", "0"},
+    {"short", "0"},
+    {"long", "0"},
+    {"bool", "false"},
+    {"float", "0.0f"},
+    {"double", "0.0"},
+  };
+}
+
+void CppCionGeneratorBase::GenStructuresForHeader(std::ofstream& stream) {
+  stream << CB_BUNDLE;
+  stream << CB_FILE;
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_STRUCTURE)
+      continue;
+    Structure& st = static_cast<Structure&>(*i);
+    GenStructureForHeader(stream, st);
+    stream << std::endl;
+  }
+}
+
+void CppCionGeneratorBase::GenStructureForHeader(std::ofstream& stream,
+                                             const Structure& st) {
+  const char ctor[] = "  $$();\n" \
+                      "  $$($$);\n";
+  const char variable[] = "$$\n";
+
+  stream << "class " << st.GetID() << " final ";
+
+  GenBrace(stream, 0, [&]() {
+    stream << " public:" << NLine(1);
+    GenTemplate(ctor, stream,
+      [&]()->std::string {
+        return st.GetID();
+      },
+      [&]()->std::string {
+        return st.GetID();
+      },
+      [&]()->std::string {
+        std::string str;
+        int n = 1;
+        for (auto& i : st.GetElements().GetElms()) {
+          if (n != 1)
+            str += ", ";
+          str += ConvertTypeToString(i->GetType()) + " " + i->GetID();
+          n++;
+        }
+        return str;
+      });
+
+    stream << NLine(1);
+    for (auto& i : st.GetElements().GetElms()) {
+      GenSetter(stream, *i);
+      GenGetter(stream, *i);
+      stream << NLine(1);
+    }
+
+    stream << " private:";
+    GenTemplate(variable, stream,
+      [&]()->std::string {
+        std::string str;
+        for (auto& i : st.GetElements().GetElms()) {
+          str += NLine(1) + Tab(1)
+              + ConvertTypeToString(i->GetType()) + " "
+              + i->GetID() + "_";
+          if (type_init_map_.find(i->GetType().ToString())
+              == type_init_map_.end()) {
+            str += ";";
+          } else {
+            str += " = " + type_init_map_[i->GetType().ToString()] + ";";
+          }
+        }
+        str += NLine(1);
+        return str;
+      });
+  }, false, false);
+  stream << ";" << NLine(1);
+}
+
+void CppCionGeneratorBase::GenSetter(std::ofstream& stream, const Element& ele) {
+  const char setter[] =
+      "void Set$$($$ $$) {\n" \
+      "  $$_ = $$;\n" \
+      "}\n";
+
+  GenTemplate(AddIndent(TAB_SIZE, setter, true), stream,
+    [&]()->std::string {
+      return ele.GetID();
+    },
+    [&]()->std::string {
+      return ConvertTypeToString(ele.GetType());
+    },
+    [&]()->std::string {
+      return ele.GetID();
+    },
+    [&]()->std::string {
+      return ele.GetID();
+    },
+    [&]()->std::string {
+      if (ele.GetType().IsUserDefinedType() ||
+        ele.GetType().GetMetaType() != nullptr ||
+        ele.GetType().ToString() == "string" ||
+        ele.GetType().ToString() == "bundle" ||
+        ele.GetType().ToString() == "file") {
+        return "std::move(" + ele.GetID() + ")";
+      }
+
+      return ele.GetID();
+    });
+  stream << NLine(1);
+}
+
+void CppCionGeneratorBase::GenGetter(std::ofstream& stream, const Element& ele) {
+  const char getter[] =
+      "$$ Get$$() const {\n" \
+      "  return $$_;\n" \
+      "}\n";
+
+  GenTemplate(AddIndent(TAB_SIZE, getter, true), stream,
+    [&]()->std::string {
+      if (ele.GetType().IsUserDefinedType() ||
+        ele.GetType().GetMetaType() != nullptr ||
+        ele.GetType().ToString() == "string" ||
+        ele.GetType().ToString() == "bundle" ||
+        ele.GetType().ToString() == "file") {
+        return "const " + ConvertTypeToString(ele.GetType()) + "&";
+      }
+
+      return ConvertTypeToString(ele.GetType());
+    },
+    [&]()->std::string {
+      return ele.GetID();
+    },
+    [&]()->std::string {
+      return ele.GetID();
+    });
+}
+
+void CppCionGeneratorBase::GenStructuresForBody(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_STRUCTURE)
+      continue;
+    Structure& st = static_cast<Structure&>(*i);
+    GenStructureForBody(stream, st);
+    stream << std::endl;
+  }
+}
+
+void CppCionGeneratorBase::GenStructureForBody(std::ofstream& stream,
+    const Structure& st) {
+  std::vector<std::pair<std::string, std::string>> v;
+  const char ctor[] = "##::##() {}\n\n" \
+                      "##::##($$)\n" \
+                      "    : $$ {}";
+
+  for (auto& i : st.GetElements().GetElms()) {
+    std::pair<std::string, std::string> p;
+
+    p.first = ConvertTypeToString(i->GetType());
+    p.second = i->GetID();
+    v.push_back(p);
+  }
+
+  GenTemplate(ReplaceAll(ctor, "##", st.GetID()), stream,
+    [&]()->std::string {
+      std::string str;
+      for (auto& i : v) {
+        str += i.first + " " + i.second;
+
+        if (i != v.back())
+          str += ", ";
+      }
+      return str;
+    },
+    [&]()->std::string {
+      std::string str;
+      for (auto& i : v) {
+        str += i.second + "_(std::move(" + i.second + "))";
+
+        if (i != v.back())
+          str += ", ";
+      }
+      return str;
+    });
+  stream <<  NLine(2);
+}
+
+void CppCionGeneratorBase::GenSerializer(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_STRUCTURE)
+      continue;
+    Structure& st = static_cast<Structure&>(*i);
+    GenSerializer(stream, st);
+    stream << NLine(1);
+  }
+}
+
+void CppCionGeneratorBase::GenPrototype(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_STRUCTURE)
+      continue;
+    Structure& st = static_cast<Structure&>(*i);
+    GenSerializer(stream, st, true);
+    GenDeSerializer(stream, st, true);
+  }
+  GenListSerializer(stream, true);
+  stream << NLine(1);
+}
+
+void CppCionGeneratorBase::GenSerializer(std::ofstream& stream, const Structure& st,
+                                     bool proto) {
+  const char parcel_str[] = "rpc_port_parcel_h";
+
+  stream << parcel_str << " operator << ("
+         << parcel_str << " h, const " << st.GetID() << "& param)";
+  if (proto) {
+    stream << ";" << NLine(1);
+    return;
+  }
+
+  stream << " ";
+  GenBrace(stream, 0, [&]() {
+    for (auto& i : st.GetElements().GetElms()) {
+      stream << AddIndent(TAB_SIZE,
+          ConvertTypeToSerializer(i->GetType(),
+              "param.Get" + i->GetID() + "()", "h"));
+    }
+    stream << Tab(1) << "return h;" << NLine(1);
+  }, false);
+}
+
+void CppCionGeneratorBase::GenDeSerializer(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_STRUCTURE)
+      continue;
+    Structure& st = static_cast<Structure&>(*i);
+    GenDeSerializer(stream, st);
+    stream << std::endl;
+  }
+}
+
+void CppCionGeneratorBase::GenDeSerializer(std::ofstream& stream,
+                                       const Structure& st, bool proto) {
+  const char parcel_str[] = "rpc_port_parcel_h";
+
+  stream << parcel_str << " operator >> ("
+         << parcel_str << " h, " << st.GetID() << "& param)";
+  if (proto) {
+    stream << ";" << NLine(1);
+    return;
+  }
+
+  stream << " ";
+  GenBrace(stream, 0, [&]() {
+    for (auto& i : st.GetElements().GetElms()) {
+      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);
+}
+
+std::string CppCionGeneratorBase::ConvertTypeToString(const BaseType& type) {
+  if (type.IsUserDefinedType()) {
+    if (IsDelegateType(type)) {
+      return "std::unique_ptr<" + type.ToString() + ">";
+    }
+    return type.ToString();
+  }
+
+  if (type.GetMetaType() != nullptr)
+    return type_map_[type.ToString()] + "<" +
+        ConvertTypeToString(*(type.GetMetaType())) + ">";
+
+  return type_map_[type.ToString()];
+}
+
+std::string CppCionGeneratorBase::Tab(int cnt) {
+  std::string t(cnt * 2, ' ');
+
+  return t;
+}
+
+std::string CppCionGeneratorBase::NLine(int cnt) {
+  std::string t(cnt, '\n');
+
+  return t;
+}
+
+void CppCionGeneratorBase::AddSerializerList(const BaseType& type) {
+  if (type.GetMetaType() != nullptr) {
+    serializer_list_[ConvertTypeToString(type)] = &type;
+    AddSerializerList(*type.GetMetaType());
+  }
+}
+
+void CppCionGeneratorBase::GenListSerializer(std::ofstream& stream,
+                                         const BaseType& type, bool proto) {
+  stream << "rpc_port_parcel_h operator << (rpc_port_parcel_h h, const "
+         << ConvertTypeToString(type) << "& c)";
+
+  if (proto) {
+    stream << ";" << NLine(1);
+    stream << "rpc_port_parcel_h operator >> (rpc_port_parcel_h h, "
+           << ConvertTypeToString(type) << "& c);" << NLine(1);
+    return;
+  }
+
+  stream << " ";
+  GenBrace(stream, 0, [&]() {
+    stream << Tab(1)
+           << "rpc_port_parcel_write_array_count(h, c.size());"
+           << NLine(1);
+    stream << Tab(1) << "for (const auto& i : c) ";
+    GenBrace(stream, TAB_SIZE, [&]() {
+      auto& mt = *type.GetMetaType();
+      stream << AddIndent(TAB_SIZE * 2, ConvertTypeToSerializer(mt, "i", "h"));
+    }, false);
+    stream << Tab(1) << "return h;" << NLine(1);
+  }, false);
+  stream << NLine(1);
+
+  stream << "rpc_port_parcel_h operator >> (rpc_port_parcel_h h, "
+         << ConvertTypeToString(type) << "& c) ";
+  GenBrace(stream, 0, [&]() {
+    stream << Tab(1) << "int l = 0;" << NLine(1);
+    stream << Tab(1)
+           << "rpc_port_parcel_read_array_count(h, &l);" << NLine(1);
+    stream << Tab(1) << "for (int i = 0; i < l; i++) ";
+    GenBrace(stream, TAB_SIZE, [&]() {
+      auto& mt = *type.GetMetaType();
+      stream << AddIndent(TAB_SIZE * 2,
+          ConvertTypeToDeserializer(mt, "v", "h", true));
+      stream << Tab(2) << "c.push_back(std::move(v));" << NLine(1);
+    }, false);
+    stream << Tab(1) << "return h;" << NLine(1);
+  }, false);
+}
+
+void CppCionGeneratorBase::GenListSerializer(std::ofstream& stream, bool proto) {
+  serializer_list_.clear();
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() == Block::TYPE_STRUCTURE) {
+      const Structure& st = static_cast<const Structure&>(*i);
+      for (auto& j : st.GetElements().GetElms()) {
+        auto& t = j->GetType();
+        AddSerializerList(t);
+      }
+    } else if (i->GetType() == Block::TYPE_INTERFACE) {
+      const Interface& iface = static_cast<const Interface&>(*i);
+      for (auto& j : iface.GetDeclarations().GetDecls()) {
+        auto& t = j->GetType();
+        AddSerializerList(t);
+        for (auto& k : j->GetParameters().GetParams()) {
+          auto& t1 = k->GetParameterType().GetBaseType();
+          AddSerializerList(t1);
+        }
+      }
+    }
+  }
+
+  for (auto& p : serializer_list_) {
+    const BaseType* t = p.second;
+    GenListSerializer(stream, *t, proto);
+  }
+}
+
+void CppCionGeneratorBase::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 CppCionGeneratorBase::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 CppCionGeneratorBase::GenParameters(std::ofstream& stream,
+                                     const Parameters& ps) {
+  stream << GetParameters(ps);
+}
+
+std::string CppCionGeneratorBase::GetParameters(const Parameters& ps) {
+  bool first = true;
+  std::string ret;
+  for (auto& i : ps.GetParams()) {
+    if (!first) {
+      ret += ", ";
+    }
+
+    std::string ref;
+    auto dir = i->GetParameterType().GetDirection();
+    if (dir == ParameterType::Direction::OUT ||
+        dir == ParameterType::Direction::REF) {
+      ref = "&";
+    }
+
+    ret += ConvertTypeToString(i->GetParameterType().GetBaseType())
+        + ref + " " + i->GetID();
+    first = false;
+  }
+
+  return ret;
+}
+
+void CppCionGeneratorBase::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 CppCionGeneratorBase::GenPrivateSharingRequest(const BaseType& type,
+    std::string id) {
+  std::string ret;
+  if (type.GetMetaType() != nullptr && (type.GetMetaType()->GetFullName() == "file")) {
+    ret += std::string("for (const auto& i : " + id + ") {\n")
+        + std::string("  std::string name = i.GetFileName();\n")
+        + std::string("  FilePayloadSend(name, service_.lock()->GetPeer());\n")
+        + std::string("}\n");
+  } else if (type.ToString() == "file") {
+    ret += std::string("std::string name = " + id + ".GetFileName();\n")
+        + std::string("FilePayloadSend(name, service_.lock()->GetPeer());\n");
+  }
+  return ret; 
+}
+
+std::string CppCionGeneratorBase::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() == "file") {
+    ret += "rpc_port_parcel_write_"
+        + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", " + id + ".GetFileName()" + ".c_str());\n";
+  } else if (type.ToString() == "bundle") {
+    ret += "rpc_port_parcel_write_bundle(" + parcel + ", "
+        + id + ".GetHandle());\n";
+  } else if (type.GetMetaType() || type.IsUserDefinedType()) {
+    if (type.IsUserDefinedType() && IsDelegateType(type))
+      ret += parcel + " << *" + id + ";\n";
+    else
+      ret += parcel + " << " + id + ";\n";
+  } else {
+    ret += "rpc_port_parcel_write_"
+        + parcel_type_map_[type.ToString()]
+        + "(" + parcel + ", " + id + ");\n";
+  }
+
+  return ret;
+}
+
+std::string CppCionGeneratorBase::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() == "file") {
+    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 += "File " + id + "(" + id + "_raw);\n";
+    } else {
+      ret +=  id + " = " + id + "_raw;\n"
+          + "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";
+    }
+  } else if (type.GetMetaType() != nullptr || type.IsUserDefinedType()) {
+    std::string n;
+
+    if (type.GetMetaType() != nullptr || IsDelegateType(type))
+      n = ConvertTypeToString(type);
+    else
+      n = type.ToString();
+
+    if (make_new_type) {
+      ret += n + " ";
+      if (IsDelegateType(type)) {
+        ret += id + "(new " + type.ToString()
+            + "(std::weak_ptr<ServiceBase>(b), stub->cion_server_));\n";
+      } else {
+        ret += id + ";\n";
+      }
+    }
+    if (IsDelegateType(type))
+      ret += parcel + " >> *" + id + ";\n";
+    else
+      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 CppCionGeneratorBase::GenBodyCallbacks(std::ofstream& stream,
+                                   const Interface& iface, bool is_proxy) {
+  stream << ReplaceAll(CB_CALLBACK_BASE, "##", iface.GetID());
+
+  for (auto& i : iface.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+          continue;
+    GenBodyCallback(stream, iface, *i, is_proxy);
+  }
+}
+
+void CppCionGeneratorBase::GenBodyCallback(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl, bool is_proxy) {
+  if (!is_proxy) {
+    GenTemplate(CB_CALLBACK_FILE_PAYLOAD_SEND, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return decl.GetID();
+      });
+
+    GenTemplate(CB_CALLBACK_INVOKE_METHOD, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return decl.GetID();
+      },
+      [&]()->std::string {
+        return GetParameters(decl.GetParameters());
+      },
+      [&]()->std::string {
+        std::string m;
+        for (auto& i : decl.GetParameters().GetParams()) {
+          auto& pt = i->GetParameterType();
+          m += AddIndent(TAB_SIZE,
+              GenPrivateSharingRequest(pt.GetBaseType(), i->GetID()));
+          m += AddIndent(TAB_SIZE,
+              ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p"));
+        }
+        return m;
+      });
+  } else {
+    GenTemplate(CB_CALLBACK_ON_RECEIVED_EVENT_METHOD, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return decl.GetID();
+      },
+      [&]()->std::string {
+        int cnt = 1;
+        std::string ret;
+        for (auto& i : decl.GetParameters().GetParams()) {
+          std::string v = "param" + std::to_string(cnt);
+          std::string c = ConvertTypeToDeserializer(
+              i->GetParameterType().GetBaseType(), v, "parcel");
+          ret += AddIndent(TAB_SIZE, c) + NLine(1);
+          cnt++;
+        }
+
+        cnt = 1;
+        ret += Tab(1) + "OnReceived(";
+        for (int i = 0; i < decl.GetParameters().GetParams().size(); i++) {
+          if (cnt != 1) {
+            ret += ", ";
+          }
+          ret += "std::move(param" + std::to_string(cnt) + ")";
+          cnt++;
+        }
+        ret += ");";
+
+        return ret;
+      });
+  }
+}
+
+void CppCionGeneratorBase::GenHeaderCallbacks(std::ofstream& stream,
+                                          const Interface& iface,
+                                          bool is_proxy) {
+  stream << CB_CALLBACK_BASE_HEADER_FRONT;
+  if (is_proxy) {
+    stream << Tab(1)
+           << "  virtual void OnReceivedEvent(rpc_port_parcel_h port) = 0;;"
+           << NLine(1);
+  }
+  stream << CB_CALLBACK_BASE_HEADER_BACK;
+
+  for (auto& i : iface.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+          continue;
+    GenHeaderCallback(stream, *i, is_proxy);
+  }
+}
+
+void CppCionGeneratorBase::GenHeaderCallback(std::ofstream& stream,
+                                         const Declaration& decl,
+                                         bool is_proxy) {
+  stream << GenTemplateString(CB_CALLBACK_CLASS,
+      [&]()->std::string {
+        return decl.GetID();
+      },
+      [&]()->std::string {
+        return ReplaceAll(
+            is_proxy ? CB_CALLBACK_CTOR_PROXY : CB_CALLBACK_CTOR_STUB,
+            "##", decl.GetID());
+      },
+      [&]()->std::string {
+        std::string ret;
+        if (is_proxy) {
+          ret = Tab(2) + "virtual void OnReceived("
+              + GetParameters(decl.GetParameters())
+              + ") {}" + NLine(1);
+        } else {
+          ret = Tab(2) + "void Invoke("
+              + GetParameters(decl.GetParameters())
+              + ");" + NLine(1);
+        }
+
+        return ret;
+      },
+      [&]()->std::string {
+        return is_proxy ? CB_CALLBACK_PRIVATE_PROXY : CB_CALLBACK_PRIVATE_STUB;
+      });
+}
+
+void CppCionGeneratorBase::GenVersion(std::ofstream& stream) {
+  GenTemplate(CB_VERSION, stream,
+    [&]()->std::string {
+      return FULLVER;
+    });
+}
+
+void CppCionGeneratorBase::GenLogTag(std::ofstream& stream, std::string id) {
+  GenTemplate(CB_LOG_TAG, stream,
+      [&]()->std::string {
+        return id;
+      });
+}
+
+void CppCionGeneratorBase::GenLogDefinition(std::ofstream& stream) {
+  stream << CB_LOG_DEF;
+}
+
+}  // namespace tidl
diff --git a/idlc/gen_cion/cpp_cion_gen_base.h b/idlc/gen_cion/cpp_cion_gen_base.h
new file mode 100644 (file)
index 0000000..d710c77
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_
+#define IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_
+
+#include <memory>
+#include <string>
+#include <map>
+
+#include "idlc/ast/type.h"
+#include "idlc/ast/structure.h"
+#include "idlc/gen/generator.h"
+
+namespace tidl {
+
+class CppCionGeneratorBase : public Generator {
+ public:
+  explicit CppCionGeneratorBase(std::shared_ptr<Document> doc);
+  virtual ~CppCionGeneratorBase() = default;
+
+  void GenVersion(std::ofstream& stream);
+  void GenStructuresForHeader(std::ofstream& stream);
+  void GenStructuresForBody(std::ofstream& stream);
+  void GenSerializer(std::ofstream& stream);
+  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);
+  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);
+  std::string GenPrivateSharingRequest(const BaseType& type, std::string id);
+  std::string GetParameters(const Parameters& ps);
+  void GenLogTag(std::ofstream& stream, std::string id);
+  void GenLogDefinition(std::ofstream& stream);
+
+ private:
+  void GenSetter(std::ofstream& stream, const Element& ele);
+  void GenGetter(std::ofstream& stream, const Element& ele);
+  void AddSerializerList(const BaseType& type);
+  void GenListSerializer(std::ofstream& stream, const BaseType& type,
+                         bool proto = false);
+  void GenDeSerializer(std::ofstream& stream, const Structure& st,
+                       bool proto = false);
+  void GenSerializer(std::ofstream& stream, const Structure& st,
+                     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;
+
+ private:
+  std::map<std::string, std::string> type_map_;
+  std::map<std::string, std::string> parcel_type_map_;
+  std::map<std::string, std::string> type_init_map_;
+  std::map<std::string, const BaseType*> serializer_list_;
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_CION_GEN_CPP_GEN_BASE_H_
diff --git a/idlc/gen_cion/cpp_cion_gen_base_cb.h b/idlc/gen_cion/cpp_cion_gen_base_cb.h
new file mode 100644 (file)
index 0000000..ab9354d
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_
+#define IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_
+
+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) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = b.raw_;
+      b.raw_ = nullptr;
+    }
+    return *this;
+  }
+
+  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+  Bundle& operator = (const Bundle& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = bundle_dup(b.GetHandle());
+    }
+    return *this;
+  }
+
+  bundle* GetHandle() const {
+    return raw_;
+  }
+
+ private:
+  bundle* raw_;
+};
+
+)__cls_bundle";
+
+const char CB_FILE[] = R"__cls_file(class File final {
+ public:
+  File() {
+  }
+
+  File(std::string filename) {
+    filename_ = filename;
+  }
+
+  std::string GetFileName() const {
+    return filename_;
+  }
+
+ private:
+  std::string filename_;
+};
+
+)__cls_file";
+
+const char CB_CALLBACK_BASE[] =
+R"__cpp_cb(
+std::atomic<int> ##::CallbackBase::seq_num_ { 0 };
+
+##::CallbackBase::CallbackBase(int delegate_id, bool once)
+    : id_(delegate_id), once_(once) {
+  seq_id_ = seq_num_++;
+}
+
+int ##::CallbackBase::GetId() const {
+  return id_;
+}
+
+int ##::CallbackBase::GetSeqId() const {
+  return seq_id_;
+}
+
+bool ##::CallbackBase::IsOnce() const {
+  return once_;
+}
+
+std::string ##::CallbackBase::GetTag() const {
+  return std::to_string(id_) + "::" + std::to_string(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_);
+  rpc_port_parcel_write_bool(h, cb.once_);
+
+  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_);
+  rpc_port_parcel_read_bool(h, &cb.once_);
+
+  return h;
+}
+)__cpp_cb";
+
+const char CB_VERSION[] =
+R"__cpp_cb(/*
+ * Generated by tidlc $$.
+ */
+)__cpp_cb";
+
+const char CB_CALLBACK_BASE_HEADER_FRONT[] =
+R"__cpp_cb(
+  class CallbackBase {
+   public:
+    CallbackBase(int delegate_id, bool once);
+    virtual ~CallbackBase() = default;
+)__cpp_cb";
+
+const char CB_CALLBACK_BASE_HEADER_BACK[] =
+R"__cpp_cb(
+    int GetId() const;
+    int GetSeqId() const;
+    bool IsOnce() const;
+    std::string GetTag() const;
+
+   private:
+    friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);
+    friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);
+
+    static std::atomic<int> seq_num_;
+    int id_;
+    int seq_id_;
+    bool once_;
+  };
+)__cpp_cb";
+
+const char CB_CALLBACK_CLASS[] =
+R"__cpp_cb(
+  class $$ : public CallbackBase {
+   public:$$
+$$
+   private:$$
+  };
+)__cpp_cb";
+
+const char CB_CALLBACK_CTOR_STUB[] =
+R"__cpp_cb(
+    ##(std::weak_ptr<ServiceBase> service, cion_server_h cion_server)
+        : CallbackBase(static_cast<int>(DelegateId::##), false) {
+      service_ = std::move(service);
+      cion_server_ = cion_server;
+    }
+)__cpp_cb";
+
+const char CB_CALLBACK_CTOR_PROXY[] =
+R"__cpp_cb(
+    ##(bool once = false)
+        : CallbackBase(static_cast<int>(DelegateId::##), once) {}
+)__cpp_cb";
+
+const char CB_CALLBACK_PRIVATE_PROXY[] =
+R"__cpp_cb(
+    void OnReceivedEvent(rpc_port_parcel_h parcel) override;
+)__cpp_cb";
+
+const char CB_CALLBACK_PRIVATE_STUB[] =
+R"__cpp_cb(
+    void FilePayloadSend(std::string path, cion_peer_info_h peer);
+
+    std::weak_ptr<ServiceBase> service_;
+    bool valid_ = true;
+    cion_server_h cion_server_;
+)__cpp_cb";
+
+const char CB_CALLBACK_FILE_PAYLOAD_SEND[] = R"__cpp_cb(
+void $$::$$::FilePayloadSend(std::string path, cion_peer_info_h peer)
+{
+  cion_payload_h pl;
+  int ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_FILE);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_create : %d", ret);
+    return;
+  }
+
+  ret = cion_payload_set_file_path(pl, path.c_str());
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_set_file_path : %d - %s", ret, path.c_str());
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  ret = cion_server_send_payload_async(cion_server_, peer, pl, nullptr, nullptr);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_send_payload_async : %d", ret);
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  cion_payload_destroy(pl);
+}
+)__cpp_cb";
+
+const char CB_CALLBACK_INVOKE_METHOD[] =
+R"__cpp_cb(
+void $$::$$::Invoke($$) {
+  if (service_.lock().get() == nullptr)
+      throw NotConnectedSocketException();
+
+  if (IsOnce() && !valid_)
+      throw InvalidCallbackException();
+
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::__Callback));
+  p << *this;
+$$
+  // Send
+  unsigned int size;
+  char *data;
+
+  int ret = rpc_port_parcel_get_raw(p, (void **)&data, &size);
+  if (ret != RPC_PORT_ERROR_NONE) {
+      _E("Failed to get raw. error(%d)", ret);
+      rpc_port_parcel_destroy(p);
+      throw InvalidIOException();
+  }
+
+  cion_payload_h pl;
+  ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_DATA);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_create : %d", ret);
+    rpc_port_parcel_destroy(p);
+    return;
+  }
+
+  ret = cion_payload_set_data(pl, (const unsigned char*)data, size);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_set_data : %d", ret);
+    rpc_port_parcel_destroy(p);
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  ret = cion_server_send_payload_async(cion_server_, service_.lock()->GetPeer(), pl, nullptr, nullptr);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_client_send_payload_async : %d", ret);
+    rpc_port_parcel_destroy(p);
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  rpc_port_parcel_destroy(p);
+  cion_payload_destroy(pl);
+  valid_ = false;
+}
+)__cpp_cb";
+
+const char CB_CALLBACK_ON_RECEIVED_EVENT_METHOD[] =
+R"__cpp_cb(
+void $$::$$::OnReceivedEvent(rpc_port_parcel_h parcel) {
+$$
+}
+)__cpp_cb";
+
+const char CB_LOG_TAG[] =
+R"__cpp_cb(
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "$$"
+)__cpp_cb";
+
+const char CB_LOG_DEF[] =
+R"__cpp_cb(
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+)__cpp_cb";
+
+#endif  // IDLC_CPP_CION_GEN_CPP_GEN_BASE_CB_H_
diff --git a/idlc/gen_cion/cpp_cion_proxy_body_gen.cc b/idlc/gen_cion/cpp_cion_proxy_body_gen.cc
new file mode 100644 (file)
index 0000000..5ea467d
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 "idlc/gen_cion/cpp_cion_proxy_body_gen.h"
+
+namespace {
+#include "idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h"
+}
+
+namespace tidl {
+
+CppCionProxyBodyGen::CppCionProxyBodyGen(std::shared_ptr<Document> doc)
+    : CppCionGeneratorBase(doc) {}
+
+void CppCionProxyBodyGen::OnInitGen(std::ofstream& stream) {
+  std::string key(".cc");
+  std::string header_file = FileName;
+
+  std::size_t found = header_file.rfind(key);
+  if (found != std::string::npos)
+    header_file.replace(found, key.length(), ".h");
+
+  GenVersion(stream);
+  stream << NLine(1);
+  stream << "#include <stdlib.h>" << NLine(1)
+         << "#include <assert.h>" << NLine(1)
+         << "#include <dlog.h>" << NLine(1)
+         <<  NLine(1)
+         << "#include \"" << header_file << "\"" << NLine(2);
+  GenLogTag(stream, "CION_PROXY");
+  GenLogDefinition(stream);
+  stream << NLine(1);
+  GenNamespace(stream);
+}
+
+void CppCionProxyBodyGen::OnFiniGen(std::ofstream& stream) {
+}
+
+void CppCionProxyBodyGen::GenNamespace(std::ofstream& stream) {
+  stream << "namespace cion ";
+  GenBrace(stream, 0, [&]() {
+    stream << "namespace " << GetFileNamespace() << " ";
+    GenBrace(stream, 0, [&]() {
+      stream <<  NLine(1);
+      GenStructuresForBody(stream);
+      stream << "namespace proxy ";
+      GenBrace(stream, 0, [&]() {
+        GenPrototype(stream);
+        GenSerializer(stream);
+        GenDeSerializer(stream);
+        GenListSerializer(stream);
+        GenInterfaces(stream);
+      }, false, false);
+      stream << "  // namespace proxy" + NLine(1);
+    }, false, false);
+    stream << "  // namespace " + GetFileNamespace() + NLine(1);
+  }, false, false);
+  stream << "  // namespace rpc_port" + NLine(1);
+}
+
+void CppCionProxyBodyGen::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 CppCionProxyBodyGen::GenInterface(std::ofstream& stream,
+                                   const Interface& iface) {
+  GenFilePayloadSend(stream, iface);
+  GenBodyCallbacks(stream, iface, true);
+  GenConstructor(stream, iface);
+  GenDestructor(stream, iface);
+  GenHelperMethods(stream, iface);
+  GenMethods(stream, iface);
+}
+
+void CppCionProxyBodyGen::GenConstructor(std::ofstream& stream,
+                                     const Interface& iface) {
+  GenTemplate(CB_PROXY_INTERFACE_CTOR, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    });
+}
+
+void CppCionProxyBodyGen::GenDestructor(std::ofstream& stream,
+                                    const Interface& iface) {
+  GenTemplate(CB_DTOR, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    });
+}
+
+void CppCionProxyBodyGen::GenHelperMethods(std::ofstream& stream,
+                                       const Interface& iface) {
+  stream << ReplaceAll(CB_PROXY_HELPER_METHODS, "##", iface.GetID())
+         << NLine(1);
+}
+
+void CppCionProxyBodyGen::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);
+  }
+}
+
+std::string CppCionProxyBodyGen::GenPrivateSharingRequestProxy(const BaseType& type,
+    std::string id) {
+  std::string ret;
+  if (type.GetMetaType() != nullptr && (type.GetMetaType()->GetFullName() == "file")) {
+    ret += std::string("for (const auto& i : " + id + ") {\n")
+        + std::string("  std::string name = i.GetFileName();\n")
+        + std::string("  FilePayloadSend(name);\n")
+        + std::string("}\n");
+  } else if (type.ToString() == "file") {
+    ret += std::string("std::string name = " + id + ".GetFileName();\n")
+        + std::string("FilePayloadSend(name);\n");
+  }
+  return ret;
+}
+
+void CppCionProxyBodyGen::GenFilePayloadSend(std::ofstream& stream,
+    const Interface& iface) {
+  GenTemplate(CB_PROXY_FILE_PAYLOAD_SEND, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    });
+}
+
+void CppCionProxyBodyGen::GenInvocation(std::ofstream& stream,
+    const Declaration& decl) {
+  stream << CB_INVOCATION_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())) {
+      l += "delegate_list_.emplace_back(" + i->GetID() + ".release());\n";
+    }
+  }
+  stream << AddIndent(TAB_SIZE, m) << NLine(1);
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
+    stream << Tab(1) << "unsigned char *return_data;" << NLine(1);
+    stream << Tab(1) << "unsigned int return_data_size = 0;" << 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);
+    if (decl.GetMethodType() == Declaration::MethodType::SYNC)
+      stream << CB_INVOCATION_SYNC_MID << NLine(1);
+    else if (decl.GetMethodType() == Declaration::MethodType::ASYNC)
+      stream << CB_INVOCATION_ASYNC_MID << NLine(1);
+  }, false, false);
+  stream << " while (false);" << NLine(1);
+
+  // Deserialize
+  if (decl.GetMethodType() == Declaration::MethodType::ASYNC) {
+    stream << Tab(1) << "rpc_port_parcel_destroy(p);"
+         << NLine(1);
+    return;
+  }
+
+  stream << CB_INVOCATION_RECEIVE << 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"));
+  }
+
+  std::string f;
+  for (auto& i : decl.GetParameters().GetParams()) {
+    auto& pt = i->GetParameterType();
+    if (pt.GetDirection() == ParameterType::Direction::OUT)
+      continue;
+    f += GenPrivateSharingRequestProxy(pt.GetBaseType(), i->GetID());
+  }
+  stream << AddIndent(TAB_SIZE, f) << NLine(1);
+
+  stream << CB_INVOCATION_END;
+}
+
+}  // namespace tidl
diff --git a/idlc/gen_cion/cpp_cion_proxy_body_gen.h b/idlc/gen_cion/cpp_cion_proxy_body_gen.h
new file mode 100644 (file)
index 0000000..da42e1a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_PROXY_BODY_GEN_H_
+#define IDLC_CPP_CION_GEN_CPP_PROXY_BODY_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+
+namespace tidl {
+
+class CppCionProxyBodyGen : public CppCionGeneratorBase {
+ public:
+  explicit CppCionProxyBodyGen(std::shared_ptr<Document> doc);
+  virtual ~CppCionProxyBodyGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenNamespace(std::ofstream& stream);
+  void GenStructures(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 GenFilePayloadSend(std::ofstream& stream, const Interface& iface);
+  void GenInvocation(std::ofstream& stream, const Declaration& decl);
+
+  std::string GenPrivateSharingRequestProxy(const BaseType& type, std::string id);
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_CION_GEN_CPP_PROXY_BODY_GEN_H_
diff --git a/idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h b/idlc/gen_cion/cpp_cion_proxy_body_gen_cb.h
new file mode 100644 (file)
index 0000000..c95685f
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_GEN_CION_CPP_PROXY_BODY_GEN_CB_H_
+#define IDLC_CPP_GEN_CION_CPP_PROXY_BODY_GEN_CB_H_
+
+const char CB_DTOR[] =
+R"__cpp_cb(
+$$::~$$() {
+}
+)__cpp_cb";
+
+const char CB_INVOCATION_PRE[] =
+R"__cpp_cb(  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+)__cpp_cb";
+
+const char CB_INVOCATION_SYNC_MID[] =
+R"__cpp_cb(
+    // SendData(SYNC)
+    unsigned int size;
+    char *data;
+
+    int ret = rpc_port_parcel_get_raw(p, (void **)&data, &size);
+    if (ret != RPC_PORT_ERROR_NONE) {
+        _E("Failed to get raw. error(%d)", ret);
+        rpc_port_parcel_destroy(p);
+        throw InvalidIOException();
+    }
+
+    ret = cion_client_send_data(cion_client_, (unsigned char *)data, size,
+        100, &return_data, &return_data_size);
+    if (ret != RPC_PORT_ERROR_NONE) {
+        _E("Failed to  cion_client_send_data : error(%d)", ret);
+        rpc_port_parcel_destroy(p);
+        throw InvalidIOException();
+    }
+
+)__cpp_cb";
+
+const char CB_INVOCATION_ASYNC_MID[] =
+R"__cpp_cb(
+    // SendPayloadAsync
+    unsigned int size;
+    char *data;
+
+    int ret = rpc_port_parcel_get_raw(p, (void **)&data, &size);
+    if (ret != RPC_PORT_ERROR_NONE) {
+      _E("Failed to get raw. error(%d)", ret);
+      rpc_port_parcel_destroy(p);
+      throw InvalidIOException();
+    }
+
+    cion_payload_h pl;
+    ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_DATA);
+    if (ret != CION_ERROR_NONE) {
+      _E("Failed to cion_payload_create : %d", ret);
+      rpc_port_parcel_destroy(p);
+      throw InvalidIOException();
+    }
+
+    ret = cion_payload_set_data(pl, (const unsigned char*)data, size);
+    if (ret != CION_ERROR_NONE) {
+      _E("Failed to cion_payload_set_data : %d", ret);
+      rpc_port_parcel_destroy(p);
+      cion_payload_destroy(pl);
+      throw InvalidIOException();
+    }
+
+    ret = cion_client_send_payload_async(cion_client_, pl, nullptr, nullptr);
+    if (ret != CION_ERROR_NONE) {
+      _E("Failed to cion_client_send_payload_async : %d", ret);
+      rpc_port_parcel_destroy(p);
+      cion_payload_destroy(pl);
+      throw InvalidIOException();
+    }
+)__cpp_cb";
+
+const char CB_INVOCATION_RECEIVE[] =
+R"__cpp_cb(
+  if (return_data_size == 0) {
+    _E("Invalid protocol");
+    rpc_port_parcel_destroy(p);
+    throw InvalidProtocolException();
+  }
+
+  rpc_port_parcel_h parcel_received;
+  rpc_port_parcel_create_from_raw(&parcel_received, return_data,
+      return_data_size);
+
+  int cmd;
+  rpc_port_parcel_read_int32(parcel_received, &cmd);
+  if (cmd != static_cast<int>(MethodId::__Result)) {
+    _E("Invalid result cmd");
+    rpc_port_parcel_destroy(p);
+    rpc_port_parcel_destroy(parcel_received);
+    throw InvalidProtocolException();
+  }
+)__cpp_cb";
+
+const char CB_INVOCATION_END[] =
+R"__cpp_cb(
+  rpc_port_parcel_destroy(p);
+  rpc_port_parcel_destroy(parcel_received);
+
+  return ret;
+)__cpp_cb";
+
+const char CB_PROXY_FILE_PAYLOAD_SEND[] = R"__cpp_cb(
+void $$::FilePayloadSend(std::string path)
+{
+  cion_payload_h pl;
+  int ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_FILE);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_create : %d", ret);
+    return;
+  }
+
+  ret = cion_payload_set_file_path(pl, path.c_str());
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_set_file_path : %d - %s", ret, path.c_str());
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  ret = cion_server_send_payload_async(cion_client_, peer_, pl, nullptr, nullptr);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_send_payload_async : %d", ret);
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  cion_payload_destroy(pl);
+}
+)__cpp_cb";
+
+const char CB_PROXY_HELPER_METHODS[] =
+R"__cpp_cb(
+void ##::Connect() {
+  if (peer_) {
+    int ret = cion_client_connect(cion_client_, peer_);
+    if (ret != CION_ERROR_NONE) {
+      _E("Failed to connect to stub. error(%d)", ret);
+      return;
+    }
+  }
+  else {
+    _E("Not discovered");
+  }
+}
+
+void ##::DisposeCallback(const std::string& tag) {
+  for (auto& i : delegate_list_) {
+    if (i->GetTag() == tag) {
+      delegate_list_.remove(i);
+      return;
+    }
+  }
+}
+
+void ##::ProcessReceivedEvent(rpc_port_parcel_h parcel) {
+  int id = 0;
+  int seq_id = 0;
+  bool once = false;
+
+  rpc_port_parcel_read_int32(parcel, &id);
+  rpc_port_parcel_read_int32(parcel, &seq_id);
+  rpc_port_parcel_read_bool(parcel, &once);
+
+  for (auto& i : delegate_list_) {
+    if (i->GetId() == id && i->GetSeqId() == seq_id) {
+      i->OnReceivedEvent(parcel);
+      if (i->IsOnce())
+        delegate_list_.remove(i);
+      break;
+    }
+  }
+}
+
+void ##::Disconnect() {
+}
+
+void ##::Discovery() {
+  int ret = cion_client_try_discovery(cion_client_, OnDiscoveredCB, nullptr);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to discovery to stub. error(%d)", ret);
+    return;
+  }
+}
+
+void ##::StopDiscovery() {
+  int ret = cion_client_stop_discovery(cion_client_);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to stop discovery. error(%d)", ret);
+    return;
+  }
+}
+
+void ##::OnConnectionResultCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_connection_result_h result,
+      void *user_data) {
+  ## *cl = static_cast<##*>(user_data);
+  cion_connection_status_e status;
+  int ret = cion_connection_result_get_status(result, &status);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_connection_result_get_status. error(%d)", ret);
+    return;
+  }
+
+  if (status == CION_CONNECTION_STATUS_OK)
+    cl->listener_->OnConnected();
+  else if (status == CION_CONNECTION_STATUS_REJECTED)
+    cl->listener_->OnRejected();
+}
+
+void ##::OnDisconnectedCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data) {
+  ## *cl = static_cast<##*>(user_data);
+  cl->delegate_list_.clear();
+  cl->listener_->OnDisconnected();
+}
+
+void ##::OnDiscoveredCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data) {
+  ## *cl = static_cast<##*>(user_data);
+  char *app_id;
+  int ret = cion_peer_info_get_app_id(peer_info, &app_id);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_peer_info_get_app_id. error(%d)", ret);
+    return;
+  }
+
+  if (std::string(app_id) == cl->target_appid_) {
+    ret = cion_peer_info_clone(peer_info, &cl->peer_);
+    if (ret != CION_ERROR_NONE) {
+      _E("Failed to cion_peer_info_clone. error(%d)", ret);
+      return;
+    }
+
+    cl->listener_->OnDiscovered();
+  }
+}
+
+void ##::OnPayloadAsyncResultCB(const cion_payload_async_result_h result,
+      void *user_data) {
+        
+      }
+
+void ##::OnPayloadReceivedCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_payload_h payload,
+      cion_payload_transfer_status_e status,
+      void *user_data) {
+  ## *cl = static_cast<##*>(user_data);
+  char *app_id;
+  int ret = cion_peer_info_get_app_id(peer_info, &app_id);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_peer_info_get_app_id. error(%d)", ret);
+    return;
+  }
+
+  if (std::string(app_id) != cl->target_appid_) {
+    _E("peer is wrong");
+    return;
+  }
+
+  cion_payload_type_e type;
+  ret = cion_payload_get_type(payload, &type);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_get_type. error(%d)", ret);
+    return;
+  }
+
+  if (type == CION_PAYLOAD_TYPE_FILE) {
+    cl->listener_->OnFileReceived(payload, peer_info, status);
+    return;
+  }
+
+  unsigned char *data;
+  unsigned int size;
+  ret = cion_payload_get_data(payload, &data, &size);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_get_data. error(%d)", ret);
+    return;
+  }
+
+  rpc_port_parcel_h parcel_received;
+  rpc_port_parcel_create_from_raw(&parcel_received, data, size);
+
+  int cmd;
+  rpc_port_parcel_read_int32(parcel_received, &cmd);
+  if (cmd != static_cast<int>(MethodId::__Callback)) {
+    rpc_port_parcel_destroy(parcel_received);
+    return;
+  }
+
+  cl->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& service_name,
+    const std::string& target_appid)
+    : listener_(listener), service_name_(service_name),
+    target_appid_(target_appid) {
+  cion_security_h security;
+  int ret = cion_security_create(&security);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to create security handle. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_client_create(&cion_client_, service_name.c_str(), security);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_client_add_disconnected_cb(cion_client_, OnDisconnectedCB,
+      this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_client_add_disconnected_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+
+  ret = cion_client_add_connection_result_cb(cion_client_, OnConnectionResultCB,
+      this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_client_add_connection_result_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_client_add_payload_received_cb(cion_client_, OnPayloadReceivedCB,
+      this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_client_add_payload_received_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+)__cpp_cb";
+
+#endif  // IDLC_CPP_GEN_CION_CPP_PROXY_BODY_GEN_CB_H_
diff --git a/idlc/gen_cion/cpp_cion_proxy_header_gen.cc b/idlc/gen_cion/cpp_cion_proxy_header_gen.cc
new file mode 100644 (file)
index 0000000..7006284
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 "idlc/gen_cion/cpp_cion_proxy_header_gen.h"
+
+namespace {
+#include "idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h"
+}
+
+namespace tidl {
+
+CppCionProxyHeaderGen::CppCionProxyHeaderGen(std::shared_ptr<Document> doc)
+    : CppCionGeneratorBase(doc) {}
+
+void CppCionProxyHeaderGen::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  stream << CB_HEADER;
+  GenNamespace(stream);
+}
+
+void CppCionProxyHeaderGen::OnFiniGen(std::ofstream& stream) {
+}
+
+void CppCionProxyHeaderGen::GenNamespace(std::ofstream& stream) {
+  stream << "namespace cion ";
+  GenBrace(stream, 0, [&]() {
+    stream << "namespace " << GetFileNamespace() << " ";
+    GenBrace(stream, 0, [&]() {
+      stream <<  NLine(1);
+      GenStructuresForHeader(stream);
+      stream << "namespace proxy ";
+      GenBrace(stream, 0, [&]() {
+        GenExceptions(stream);
+        GenInterfaces(stream);
+      }, false, false);
+      stream << "  // namespace proxy" + NLine(1);
+    }, false, false);
+    stream << "  // namespace " + GetFileNamespace() + NLine(1);
+  }, false, false);
+  stream << "  // namespace cion" + NLine(1);
+}
+
+void CppCionProxyHeaderGen::GenExceptions(std::ofstream& stream) {
+  stream << CB_EXCEPTIONS;
+}
+
+void CppCionProxyHeaderGen::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 CppCionProxyHeaderGen::GenInterface(std::ofstream& stream,
+                                     const Interface& iface) {
+  stream << NLine(1) << "class " << iface.GetID() << " final ";
+  GenBrace(stream, 0, [&]() {
+    stream << " public:" << NLine(1);
+    GenHeaderCallbacks(stream, iface, true);
+    GenTemplate(CB_PUBLIC_MEMBERS, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return iface.GetID();
+      });
+    GenMethods(stream, iface);
+    GenDelegateId(stream, iface);
+    stream << NLine(1) << " private:" << NLine(1);
+    GenMethodId(stream, iface);
+    stream << CB_PRIVATE_MEMBERS;
+  }, false, false);
+  stream << ";" << NLine(1);
+}
+
+void CppCionProxyHeaderGen::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 CppCionProxyHeaderGen::GenDeclaration(std::ofstream& stream,
+                                       const Declaration& decl) {
+  if (!decl.GetComments().empty())
+    stream << NLine(1) << AddIndent(TAB_SIZE, decl.GetComments());
+
+  stream << Tab(1) << ConvertTypeToString(decl.GetType()) << " "
+         << decl.GetID() << "(";
+  GenParameters(stream, decl.GetParameters());
+  stream << ");" << NLine(1);
+}
+}  // namespace tidl
diff --git a/idlc/gen_cion/cpp_cion_proxy_header_gen.h b/idlc/gen_cion/cpp_cion_proxy_header_gen.h
new file mode 100644 (file)
index 0000000..c9eba7c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_H_
+#define IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+
+namespace tidl {
+
+class CppCionProxyHeaderGen : public CppCionGeneratorBase {
+ public:
+  explicit CppCionProxyHeaderGen(std::shared_ptr<Document> doc);
+  virtual ~CppCionProxyHeaderGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ 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);
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_H_
diff --git a/idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h b/idlc/gen_cion/cpp_cion_proxy_header_gen_cb.h
new file mode 100644 (file)
index 0000000..d09e7e1
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_
+#define IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_
+
+const char CB_EXCEPTIONS[] =
+R"__cpp_cb(
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class PermissionDeniedException : public Exception {};
+class InvalidIDException : public Exception {};
+)__cpp_cb";
+
+const char CB_PUBLIC_MEMBERS[] =
+R"__cpp_cb(
+  class IEventListener {
+   public:
+    /// <summary>
+    /// This method will be invoked when the client app is connected to the service app.
+    /// </summary>
+    virtual void OnConnected() = 0;
+
+    /// <summary>
+    /// This method will be invoked after the client app was disconnected from the service app.
+    /// </summary>
+    virtual void OnDisconnected() = 0;
+
+    /// <summary>
+    /// This method will be invoked when the service app rejects the client app.
+    /// </summary>
+    virtual void OnRejected() = 0;
+
+    /// <summary>
+    /// This method will be invoked when the service app is discovered.
+    /// </summary>
+    virtual void OnDiscovered() = 0;
+
+    /// <summary>
+    /// This method will be invoked when file receieved from service.
+    /// </summary>
+    virtual void OnFileReceived(cion_peer_info_h peer_info,
+        cion_payload_h file_payload, cion_payload_transfer_status_e status) = 0;
+  };
+
+  /// <summary>
+  /// Constructor for this class
+  /// </summary>
+  /// <param name="service_name">The service name for </param>
+  explicit $$(IEventListener* listener, const std::string& service_name,
+      const std::string& target_appid);
+
+  /// <summary>
+  /// Destructor for this class
+  /// </summary>
+  virtual ~$$();
+
+  /// <summary>
+  /// Connects to the service app.
+  /// </summary>
+  void Connect();
+
+  /// <summary>
+  /// Disconnects to the service app.
+  /// </summary>
+  void Disconnect();
+
+  void Discovery();
+  void StopDiscovery();
+
+   /// <summary>
+  /// Disposes delegate objects in this interface
+  /// </summary>
+  /// <param name="tag">The tag string from delegate object</param>
+  void DisposeCallback(const std::string& tag);
+)__cpp_cb";
+
+const char CB_PRIVATE_MEMBERS[] =
+R"__cpp_cb(  void ProcessReceivedEvent(rpc_port_parcel_h parcel);
+  void FilePayloadSend(std::string path);
+
+  static void OnConnectionResultCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_connection_result_h result,
+      void *user_data);
+  static void OnDisconnectedCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data);
+  static void OnDiscoveredCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data);
+  static void OnPayloadAsyncResultCB(const cion_payload_async_result_h result,
+      void *user_data);
+  static void OnPayloadReceivedCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_payload_h payload,
+      cion_payload_transfer_status_e status,
+      void *user_data);
+
+  cion_client_h cion_client_;
+  cion_peer_info_h peer_;
+  IEventListener* listener_;
+  std::string service_name_;
+  std::string target_appid_;
+  std::recursive_mutex mutex_;
+  std::list<std::unique_ptr<CallbackBase>> delegate_list_;
+)__cpp_cb";
+
+const char CB_HEADER[] =
+R"__cpp_cb(
+#pragma once
+
+#include <cion.h>
+#include <rpc-port-parcel.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <memory>
+#include <mutex>
+#include <atomic>
+
+)__cpp_cb";
+
+#endif  // IDLC_CPP_CION_GEN_CPP_PROXY_HEADER_GEN_CB_H_
diff --git a/idlc/gen_cion/cpp_cion_stub_body_gen.cc b/idlc/gen_cion/cpp_cion_stub_body_gen.cc
new file mode 100644 (file)
index 0000000..56b90fb
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 "idlc/gen_cion/cpp_cion_stub_body_gen.h"
+
+namespace {
+#include "idlc/gen_cion/cpp_cion_stub_body_gen_cb.h"
+}
+
+namespace tidl {
+
+CppCionStubBodyGen::CppCionStubBodyGen(std::shared_ptr<Document> doc,
+    std::shared_ptr<Options> options)
+    : CppCionGeneratorBase(doc), options_(options) {}
+
+void CppCionStubBodyGen::OnInitGen(std::ofstream& stream) {
+  std::string key(".cc");
+  std::string header_file = FileName;
+
+  std::size_t found = header_file.rfind(key);
+  if (found != std::string::npos)
+    header_file.replace(found, key.length(), ".h");
+
+  GenVersion(stream);
+  stream << NLine(1);
+  stream << "#include <stdlib.h>" << NLine(1)
+         << "#include <assert.h>" << NLine(1)
+         << "#include <libgen.h>" << NLine(1)
+         << "#include <dlog.h>" << NLine(1)
+         << NLine(1)
+         << "#include \"" << header_file << "\"" << NLine(2);
+  GenLogTag(stream, "CION_STUB");
+  GenLogDefinition(stream);
+  stream << NLine(1);
+  GenNamespace(stream);
+}
+
+void CppCionStubBodyGen::OnFiniGen(std::ofstream& stream) {}
+
+void CppCionStubBodyGen::GenNamespace(std::ofstream& stream) {
+  stream << "namespace cion ";
+  GenBrace(stream, 0, [&]() {
+    stream << "namespace " << GetFileNamespace() << " ";
+    GenBrace(stream, 0, [&]() {
+      stream << NLine(1);
+      GenStructuresForBody(stream);
+      stream << "namespace stub ";
+      GenBrace(stream, 0, [&]() {
+        GenPrototype(stream);
+        GenSerializer(stream);
+        GenDeSerializer(stream);
+        GenListSerializer(stream);
+        GenInterfaces(stream);
+      }, false, false);
+      stream << "  // namespace stub" + NLine(1);
+    }, false, false);
+    stream << "  // namespace " + GetFileNamespace() + NLine(1);
+  }, false, false);
+  stream << "  // namespace cion" + NLine(1);
+}
+
+void CppCionStubBodyGen::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 CppCionStubBodyGen::GenInterface(std::ofstream& stream,
+                                    const Interface& iface) {
+  GenFilePayloadSend(stream, iface);
+  GenServiceBase(stream, iface);
+  GenBodyCallbacks(stream, iface, false);
+  GenDefaultMethods(stream, iface);
+  GenCionDataReceivedEvent(stream, iface);
+  GenCionPayloadReceivedEvent(stream, iface);
+}
+
+void CppCionStubBodyGen::GenServiceBase(std::ofstream& stream,
+                                    const Interface& iface) {
+  GenTemplate(CB_CTOR_SERVICE_BASE, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    });
+  stream << NLine(1);
+}
+
+void CppCionStubBodyGen::GenConstructor(std::ofstream& stream,
+                                    const Interface& iface) {
+  stream << ReplaceAll(CB_CTOR_FRONT, "##", iface.GetID());
+}
+
+void CppCionStubBodyGen::GenDefaultMethods(std::ofstream& stream,
+                                       const Interface& iface) {
+  GenConstructor(stream, iface);
+  if (options_->IsThreadEnabled())
+    stream << ReplaceAll(CB_DEFAULT_THREAD_METHODS, "##", iface.GetID());
+
+  stream << ReplaceAll(CB_DEFAULT_METHODS, "##", iface.GetID());
+}
+
+void CppCionStubBodyGen::GenCionDataReceivedEvent(std::ofstream& stream,
+                                      const Interface& iface) {
+  if (options_->IsThreadEnabled()) {
+    GenTemplate(CB_RUN_PENDING_JOB_FRONT, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      });
+  } else {
+    GenTemplate(CB_CION_ON_DATA_RECEIVED_CB_FRONT, stream,
+      [&]()->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 ||
+        i->GetMethodType() == Declaration::MethodType::ASYNC)
+      continue;
+    stream << Tab(2) << "case static_cast<int>(MethodId::"
+           << i->GetID() << "): ";
+    GenBrace(stream, TAB_SIZE * 2, [&]() {
+      GenInvocation(stream, *i);
+      stream << Tab(3) << "break;" << NLine(1);
+    }, false);
+    stream << NLine(1);
+  }
+
+  if (options_->IsThreadEnabled()) {
+    stream << CB_RUN_PENDING_JOB_BACK << NLine(1);
+
+    GenTemplate(CB_ON_DATA_RECEIVED_CB, stream,
+      [&]()->std::string {
+        return iface.GetID();
+      },
+      [&]()->std::string {
+        return iface.GetID();
+      });
+  } else {
+    stream << CB_CION_ON_DATA_RECEIVED_CB_BACK << NLine(1);
+  }
+}
+
+void CppCionStubBodyGen::GenCionPayloadReceivedEvent(std::ofstream& stream,
+                                      const Interface& iface) {
+  GenTemplate(CB_CION_ON_PAYLOAD_RECEIVED_CB_FRONT, stream,
+    [&]()->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 ||
+        i->GetMethodType() == Declaration::MethodType::SYNC)
+      continue;
+    stream << Tab(2) << "case static_cast<int>(MethodId::"
+           << i->GetID() << "): ";
+    GenBrace(stream, TAB_SIZE * 2, [&]() {
+      GenInvocation(stream, *i);
+      stream << Tab(3) << "break;" << NLine(1);
+    }, false);
+    stream << NLine(1);
+  }
+
+  stream << CB_CION_ON_PAYLOAD_RECEIVED_CB_BACK << NLine(1);
+}
+
+std::string CppCionStubBodyGen::GenPrivateSharingRequestStub(const BaseType& type,
+    std::string id) {
+  std::string ret;
+  if (type.GetMetaType() != nullptr && (type.GetMetaType()->GetFullName() == "file")) {
+    ret += std::string("for (const auto& i : " + id + ") {\n")
+        + std::string("  std::string name = i.GetFileName();\n")
+        + std::string("  stub->FilePayloadSend(name, b->GetPeer());\n")
+        + std::string("}\n");
+  } else if (type.ToString() == "file") {
+    ret += std::string("std::string name = " + id + ".GetFileName();\n")
+        + std::string("stub->FilePayloadSend(name, b->GetPeer());\n");
+  }
+  return ret;
+}
+
+void CppCionStubBodyGen::GenInvocation(std::ofstream& stream,
+    const Declaration& decl) {
+  int cnt = 1;
+
+  // Deserialize
+  for (auto& i : decl.GetParameters().GetParams()) {
+    if (i->GetParameterType().GetDirection() == ParameterType::Direction::OUT) {
+      cnt++;
+      continue;
+    }
+
+    std::string v = "param" + std::to_string(cnt);
+    std::string c = ConvertTypeToDeserializer(
+        i->GetParameterType().GetBaseType(), v, "p");
+    stream << AddIndent(TAB_SIZE * 3, c);
+    cnt++;
+  }
+
+  // Invoke
+  cnt = 1;
+  std::string m;
+  std::string d;
+  bool hasRet = false;
+
+  if (decl.GetType().ToString() != "void") {
+    m += "auto retVal = ";
+    hasRet = true;
+  }
+
+  m += "b->" + decl.GetID() + "(";
+  for (auto& i : decl.GetParameters().GetParams()) {
+    if (cnt != 1) {
+      m += ", ";
+    }
+
+    std::string v = "param" + std::to_string(cnt);
+    auto& pt = i->GetParameterType();
+    if (pt.GetDirection() == ParameterType::Direction::OUT) {
+      d += ConvertTypeToString(pt.GetBaseType()) + " " + v + ";\n";
+    }
+    if (IsDelegateType(pt.GetBaseType())) {
+      m += "std::move(";
+      m += v;
+      m += ")";
+    } else {
+      m += v;
+    }
+    cnt++;
+  }
+
+  m += ");\n";
+  stream << AddIndent(TAB_SIZE * 3, d);
+  stream << AddIndent(TAB_SIZE * 3, m);
+
+  // Serialize
+  if (decl.GetMethodType() == Declaration::MethodType::ASYNC)
+    return;
+
+  cnt = 0;
+  m = "rpc_port_parcel_write_int32(" \
+      "result, static_cast<int>(MethodId::__Result));\n";
+  for (auto& i : decl.GetParameters().GetParams()) {
+    auto& pt = i->GetParameterType();
+    cnt++;
+    if (pt.GetDirection() == ParameterType::Direction::IN)
+      continue;
+    m += GenPrivateSharingRequestStub(pt.GetBaseType(), "param" + std::to_string(cnt));
+    m += ConvertTypeToSerializer(pt.GetBaseType(),
+                                "param" + std::to_string(cnt), "result");
+  }
+
+  if (hasRet) {
+    m += GenPrivateSharingRequestStub(decl.GetType(), "retVal");
+    m += ConvertTypeToSerializer(decl.GetType(), "retVal", "result");
+  }
+
+  //m += "_I(\"retVal(%d)\", retVal);\n";
+  stream << AddIndent(TAB_SIZE * 3, m);
+}
+
+void CppCionStubBodyGen::GenFilePayloadSend(std::ofstream& stream,
+    const Interface& iface) {
+  GenTemplate(CB_FILE_PAYLOAD_SEND, stream,
+    [&]()->std::string {
+      return iface.GetID();
+    });
+  stream << NLine(1);
+}
+
+}  // namespace tidl
diff --git a/idlc/gen_cion/cpp_cion_stub_body_gen.h b/idlc/gen_cion/cpp_cion_stub_body_gen.h
new file mode 100644 (file)
index 0000000..747aa68
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_
+#define IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+#include "idlc/options.h"
+
+namespace tidl {
+
+class CppCionStubBodyGen : public CppCionGeneratorBase {
+ public:
+  explicit CppCionStubBodyGen(std::shared_ptr<Document> doc, std::shared_ptr<Options> options);
+  virtual ~CppCionStubBodyGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenNamespace(std::ofstream& stream);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenServiceBase(std::ofstream& stream, const Interface& iface);
+  void GenDefaultMethods(std::ofstream& stream, const Interface& iface);
+  void GenCionDataReceivedEvent(std::ofstream& stream, const Interface& iface);
+  void GenCionPayloadReceivedEvent(std::ofstream& stream, const Interface& iface);
+  void GenInvocation(std::ofstream& stream, const Declaration& decl);
+  void GenConstructor(std::ofstream& stream, const Interface& iface);
+  void GenFilePayloadSend(std::ofstream& stream, const Interface& iface);
+  std::string GenPrivateSharingRequestStub(const BaseType& type, std::string id);
+
+ private:
+  std::shared_ptr<Options> options_;
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_H_
diff --git a/idlc/gen_cion/cpp_cion_stub_body_gen_cb.h b/idlc/gen_cion/cpp_cion_stub_body_gen_cb.h
new file mode 100644 (file)
index 0000000..9a28cb5
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_CB_H_
+#define IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_CB_H_
+
+const char CB_CTOR_FRONT[] =
+R"__cpp_cb(
+##::##(const std::string& service_name, const std::string& display_name) {
+  cion_security_h security;
+  int ret = cion_security_create(&security);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to create security handle. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_server_create(&cion_server_, service_name.c_str(),
+      display_name.c_str(), security);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_server_add_connection_result_cb(cion_server_, OnConnectionResultCB,
+      this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_add_connection_result_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_server_add_payload_received_cb(cion_server_, OnPayloadReceivedCB,
+      this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_add_payload_received_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_server_set_data_received_cb(cion_server_, OnDataReceivedCB, this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_set_data_received_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  ret = cion_server_add_disconnected_cb(cion_server_, OnDisconnectedCB, this);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_add_disconnected_cb. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+)__cpp_cb";
+
+const char CB_DEFAULT_METHODS[] =
+R"__cpp_cb(
+##::~##() {
+  for (auto& i : services_) {
+    i->OnTerminate();
+  }
+}
+
+void ##::Listen(std::shared_ptr<##::ServiceBase::Factory> service_factory) {
+  service_factory_ = std::move(service_factory);
+  int ret = cion_server_listen(cion_server_, OnConnectionRequestCB, nullptr);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_listen. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void ##::Accept(std::shared_ptr<ServiceBase> service) {
+  auto p = service->GetPeer();
+  int ret = cion_server_accept(cion_server_, p);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_accept. error(%d)", ret);
+    throw InvalidIOException();
+  }
+
+  service->OnCreate();
+  services_.emplace_back(std::move(service));
+}
+
+void ##::Reject(std::shared_ptr<ServiceBase> service, std::string reason) {
+  auto p = service->GetPeer();
+  int ret = cion_server_reject(cion_server_, p, reason.c_str());
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_reject. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void ##::Disconnect(std::shared_ptr<ServiceBase> service) {
+  auto p = service->GetPeer();
+  int ret = cion_server_disconnect(cion_server_, p);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_disconnect. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void ##::OnConnectionResultCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_connection_result_h result,
+      void *user_data) {
+}
+
+void ##::OnDisconnectedCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data) {
+  ##* stub = static_cast<##*>(user_data);
+  char *peer_app_id, *peer_uuid;
+  cion_peer_info_get_app_id(peer_info, &peer_app_id);
+  cion_peer_info_get_app_id(peer_info, &peer_uuid);
+
+  for (auto s = stub->services_.begin();
+      s != stub->services_.end(); s++) {
+    char *service_app_id, *service_uuid;
+    cion_peer_info_get_app_id(s->get()->GetPeer(), &service_app_id);
+    cion_peer_info_get_app_id(s->get()->GetPeer(), &service_uuid);
+    if (strcmp(peer_app_id, service_app_id) == 0 &&
+        strcmp(peer_uuid, service_uuid)) {
+      stub->services_.erase(s);
+      return;
+    }
+  }
+}
+
+void ##::OnConnectionRequestCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data) {
+  ##* stub = static_cast<##*>(user_data);
+  auto s = stub->service_factory_->CreateService(peer_info);
+  s->OnRequested(s);
+}
+
+)__cpp_cb";
+
+const char CB_DEFAULT_THREAD_METHODS[] =
+R"__cpp_cb(
+void ##::ServiceBase::Dispatch(rpc_port_h port,
+                            rpc_port_h callback_port,
+                            rpc_port_parcel_h parcel,
+                            std::shared_ptr<ServiceBase> service) {
+  active_object_->Send(
+      std::shared_ptr<Job>(
+        new (std::nothrow) PendingJob(
+          port, callback_port, parcel, service)));
+}
+
+##::PendingJob::PendingJob(rpc_port_h port,
+                                   rpc_port_h callback_port,
+                                   rpc_port_parcel_h parcel,
+                                   std::shared_ptr<ServiceBase> service)
+  : Job(this),
+    port_(port),
+    callback_port_(callback_port),
+    parcel_(parcel),
+    service_(std::move(service)) {
+}
+
+)__cpp_cb";
+
+const char CB_RUN_PENDING_JOB_FRONT[] =
+R"__cpp_cb(
+void $$::PendingJob::Run() {
+  rpc_port_parcel_h result;
+  int cmd;
+  int ret;
+  rpc_port_parcel_h p = parcel_;
+  std::shared_ptr<ServiceBase> b = service_;
+  rpc_port_h port = port_;
+
+  rpc_port_parcel_create(&result);
+  rpc_port_parcel_read_int32(parcel_, &cmd);
+
+  switch (cmd) {
+)__cpp_cb";
+
+const char CB_RUN_PENDING_JOB_BACK[] =
+R"__cpp_cb(    default:
+      _E("Unknown command(%d)", cmd);
+      rpc_port_parcel_destroy(parcel_);
+      rpc_port_parcel_destroy(result);
+      return;
+  }
+
+  rpc_port_parcel_destroy(parcel_);
+  rpc_port_parcel_destroy(result);
+}
+)__cpp_cb";
+
+const char CB_ON_DATA_RECEIVED_CB[] =
+R"__cpp_cb(
+int $$::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)
+{
+  auto* cxt = static_cast<$$*>(data);
+  std::shared_ptr<ServiceBase> b;
+  rpc_port_parcel_h parcel;
+  rpc_port_h callback_port;
+
+  for (auto& i : cxt->services_) {
+    if (i->GetInstance() == instance) {
+      b = i;
+      break;
+    }
+  }
+
+  if (b.get() == nullptr) {
+    _E("Failed to find $$ context(%s)", instance);
+    return -1;
+  }
+
+  int ret = rpc_port_stub_get_port(cxt->stub_, RPC_PORT_PORT_CALLBACK, instance,
+      &callback_port);
+  if (ret != 0) {
+    _E("Failed to get callback port");
+  }
+
+  ret = rpc_port_parcel_create_from_port(&parcel, port);
+  if (ret != 0) {
+    _E("Failed to create parcel from port");
+    return ret;
+  }
+  b->Dispatch(port, callback_port, parcel, b);
+
+  return ret;
+}
+)__cpp_cb";
+
+const char CB_CTOR_SERVICE_BASE[] =
+R"__cpp_cb($$::ServiceBase::ServiceBase(cion_peer_info_h peer)
+    : active_object_(new ActiveObject()) {
+  int ret = cion_peer_info_clone(peer, &peer_);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_peer_info_clone. error(%d)", ret);
+    return;
+  }
+})__cpp_cb";
+
+
+const char CB_FILE_PAYLOAD_SEND[] = R"__cpp_cb(
+void $$::FilePayloadSend(std::string path, cion_peer_info_h peer)
+{
+  cion_payload_h pl;
+  int ret = cion_payload_create(&pl, CION_PAYLOAD_TYPE_FILE);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_create : %d", ret);
+    return;
+  }
+
+  ret = cion_payload_set_file_path(pl, path.c_str());
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_set_file_path : %d - %s", ret, path.c_str());
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  ret = cion_server_send_payload_async(cion_server_, peer, pl, nullptr, nullptr);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_server_send_payload_async : %d", ret);
+    cion_payload_destroy(pl);
+    return;
+  }
+
+  cion_payload_destroy(pl);
+}
+)__cpp_cb";
+
+const char CB_CION_ON_PAYLOAD_RECEIVED_CB_FRONT[] =
+R"__cpp_cb(
+void $$::OnPayloadReceivedCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_payload_h payload,
+      cion_payload_transfer_status_e status,
+      void *user_data) {
+  $$* stub = static_cast<$$*>(user_data);
+  std::shared_ptr<ServiceBase> b;
+  rpc_port_parcel_h p;
+  char *peer_app_id, *peer_uuid;
+  cion_peer_info_get_app_id(peer_info, &peer_app_id);
+  cion_peer_info_get_app_id(peer_info, &peer_uuid);
+
+  for (auto& s : stub->services_) {
+    char *service_app_id, *service_uuid;
+    cion_peer_info_get_app_id(s->GetPeer(), &service_app_id);
+    cion_peer_info_get_app_id(s->GetPeer(), &service_uuid);
+    if (strcmp(peer_app_id, service_app_id) == 0 &&
+        strcmp(peer_uuid, service_uuid)) {
+      b = s;
+      break;
+    }
+  }
+
+  if (b.get() == nullptr) {
+    _E("Failed to find service base(%s)", peer_app_id);
+    return;
+  }
+
+  cion_payload_type_e type;
+  int ret = cion_payload_get_type(payload, &type);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_get_type. error(%d)", ret);
+    return;
+  }
+
+  if (type == CION_PAYLOAD_TYPE_FILE) {
+    b->OnFileReceived(payload, peer_info, status);
+    return;
+  }
+
+  unsigned char *data;
+  unsigned int size;
+  ret = cion_payload_get_data(payload, &data, &size);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_get_data. error(%d)", ret);
+    return;
+  }
+
+  ret = rpc_port_parcel_create_from_raw(&p, data, size);
+  if (ret != 0) {
+    _E("Failed to create parcel from port");
+    return;
+  }
+
+  int cmd;
+  rpc_port_parcel_read_int32(p, &cmd);
+
+  switch (cmd) {
+)__cpp_cb";
+
+const char CB_CION_ON_PAYLOAD_RECEIVED_CB_BACK[] =
+R"__cpp_cb(    default:
+      _E("Unknown command(%d)", cmd);
+      rpc_port_parcel_destroy(p);
+  }
+
+  rpc_port_parcel_destroy(p);
+
+}
+)__cpp_cb";
+
+const char CB_CION_ON_DATA_RECEIVED_CB_FRONT[] =
+R"__cpp_cb(
+void $$::OnDataReceivedCB(const char *service_name,
+      const cion_peer_info_h peer_info, const unsigned char *data,
+      unsigned int data_size, unsigned char **return_data,
+      unsigned int *return_data_size, void *user_data) {
+  $$* stub = static_cast<$$*>(user_data);
+  std::shared_ptr<ServiceBase> b;
+  rpc_port_parcel_h p;
+  char *peer_app_id, *peer_uuid;
+  cion_peer_info_get_app_id(peer_info, &peer_app_id);
+  cion_peer_info_get_app_id(peer_info, &peer_uuid);
+
+  for (auto& s : stub->services_) {
+    char *service_app_id, *service_uuid;
+    cion_peer_info_get_app_id(s->GetPeer(), &service_app_id);
+    cion_peer_info_get_app_id(s->GetPeer(), &service_uuid);
+    if (strcmp(peer_app_id, service_app_id) == 0 &&
+        strcmp(peer_uuid, service_uuid)) {
+      b = s;
+      break;
+    }
+  }
+
+  int ret = rpc_port_parcel_create_from_raw(&p, data, data_size);
+  if (ret != 0) {
+    _E("Failed to create parcel from port");
+    return;
+  }
+
+  int cmd;
+  rpc_port_parcel_read_int32(p, &cmd);
+
+  rpc_port_parcel_h result = nullptr;
+  rpc_port_parcel_create(&result);
+  switch (cmd) {
+)__cpp_cb";
+
+const char CB_CION_ON_DATA_RECEIVED_CB_BACK[] =
+R"__cpp_cb(    default:
+      _E("Unknown command(%d)", cmd);
+      rpc_port_parcel_destroy(p);
+      rpc_port_parcel_destroy(result);
+      return;
+  }
+
+  ret = rpc_port_parcel_get_raw(result, (void **)return_data, return_data_size);
+  if (ret != RPC_PORT_ERROR_NONE) {
+      _E("Failed to get raw. error(%d)", ret);
+      rpc_port_parcel_destroy(p);
+      rpc_port_parcel_destroy(result);
+      return;
+  }
+
+  rpc_port_parcel_destroy(p);
+  rpc_port_parcel_destroy(result);
+}
+)__cpp_cb";
+
+#endif  // IDLC_CPP_CION_GEN_CPP_STUB_BODY_GEN_CB_H_
diff --git a/idlc/gen_cion/cpp_cion_stub_header_gen.cc b/idlc/gen_cion/cpp_cion_stub_header_gen.cc
new file mode 100644 (file)
index 0000000..389a673
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 "idlc/gen_cion/cpp_cion_stub_header_gen.h"
+
+namespace {
+#include "idlc/gen_cion/cpp_cion_stub_header_gen_cb.h"
+}
+
+namespace tidl {
+
+CppCionStubHeaderGen::CppCionStubHeaderGen(std::shared_ptr<Document> doc,
+      std::shared_ptr<Options> options)
+    : CppCionGeneratorBase(doc), options_(options) {}
+
+void CppCionStubHeaderGen::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  stream << CB_HEADER;
+  GenNamespace(stream);
+}
+
+void CppCionStubHeaderGen::OnFiniGen(std::ofstream& stream) {
+}
+
+void CppCionStubHeaderGen::GenNamespace(std::ofstream& stream) {
+  stream << "namespace cion ";
+  GenBrace(stream, 0, [&]() {
+    stream << "namespace " << GetFileNamespace() << " ";
+    GenBrace(stream, 0, [&]() {
+      stream << NLine(1);
+      GenStructuresForHeader(stream);
+      stream << "namespace stub ";
+      GenBrace(stream, 0, [&]() {
+        GenExceptions(stream);
+        stream << CB_JOB;
+        stream << CB_SHARED_QUEUE;
+        stream << CB_ACTIVE_OBJECT;
+        GenInterfaces(stream);
+      }, false, false);
+      stream << "  // namespace stub" + NLine(1);
+    }, false, false);
+    stream << "  // namespace " + GetFileNamespace() + NLine(1);
+  }, false, false);
+  stream << "  // namespace cion" + NLine(1);
+}
+
+void CppCionStubHeaderGen::GenExceptions(std::ofstream& stream) {
+  stream << CB_EXCEPTIONS;
+}
+
+void CppCionStubHeaderGen::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 CppCionStubHeaderGen::GenInterface(std::ofstream& stream,
+                                    const Interface& iface) {
+  stream << NLine(1) << "class " << iface.GetID() << " final ";
+  GenBrace(stream, 0, [&]() {
+    GenPublic(stream, iface);
+    GenPrivate(stream, iface);
+  }, false, false);
+  stream << ";" << NLine(1);
+}
+
+void CppCionStubHeaderGen::GenPublic(std::ofstream& stream,
+                                 const Interface& iface) {
+  stream << " public:" << NLine(1);
+  stream << "  class ServiceBase;" << NLine(1);
+  GenHeaderCallbacks(stream, iface, false);
+  if (options_->IsThreadEnabled())
+    stream << CB_PENDING_JOB << NLine(1);
+  GenServiceBase(stream, iface);
+  GenPublicMethods(stream, iface);
+}
+
+void CppCionStubHeaderGen::GenPrivate(std::ofstream& stream,
+                                 const Interface& iface) {
+  stream << " private:" << NLine(1);
+  GenMethodId(stream, iface);
+  GenDelegateId(stream, iface);
+  stream << CB_PRIVATE_MEMBERS;
+}
+
+void CppCionStubHeaderGen::GenServiceBase(std::ofstream& stream,
+                                      const Interface& iface) {
+  stream << CB_SERVICE_BASE_FRONT;
+  auto& decls = iface.GetDeclarations();
+
+  for (auto& i : decls.GetDecls()) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+    if (!i->GetComments().empty())
+      stream << NLine(1) << AddIndent(TAB_SIZE * 2, i->GetComments());
+    stream << Tab(2) << "virtual " << ConvertTypeToString(i->GetType())
+           << " " << i->GetID() << "(";
+    GenParameters(stream, i->GetParameters());
+    stream << ") = 0;" << NLine(1);
+  }
+
+  stream << CB_SERVICE_BASE_BACK << NLine(2);
+}
+
+void CppCionStubHeaderGen::GenPublicMethods(std::ofstream& stream,
+                                        const Interface& iface) {
+  stream << ReplaceAll(CB_PUBLIC_METHODS, "##", iface.GetID());
+}
+
+}  // namespace tidl
diff --git a/idlc/gen_cion/cpp_cion_stub_header_gen.h b/idlc/gen_cion/cpp_cion_stub_header_gen.h
new file mode 100644 (file)
index 0000000..634217b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_H_
+#define IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen_cion/cpp_cion_gen_base.h"
+#include "idlc/options.h"
+
+namespace tidl {
+
+class CppCionStubHeaderGen : public CppCionGeneratorBase {
+ public:
+  explicit CppCionStubHeaderGen(std::shared_ptr<Document> doc,
+      std::shared_ptr<Options> options);
+  virtual ~CppCionStubHeaderGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenExceptions(std::ofstream& stream);
+  void GenNamespace(std::ofstream& stream);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenPublic(std::ofstream& stream, const Interface& iface);
+  void GenPrivate(std::ofstream& stream, const Interface& iface);
+  void GenServiceBase(std::ofstream& stream, const Interface& iface);
+  void GenPublicMethods(std::ofstream& stream, const Interface& iface);
+
+ private:
+  std::shared_ptr<Options> options_;
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_GEN_CPP_STUB_HEADER_GEN_H_
diff --git a/idlc/gen_cion/cpp_cion_stub_header_gen_cb.h b/idlc/gen_cion/cpp_cion_stub_header_gen_cb.h
new file mode 100644 (file)
index 0000000..5cb1e34
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_
+#define IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_
+
+const char CB_EXCEPTIONS[] =
+R"__cpp_cb(
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class InvalidCallbackException : public Exception {};
+)__cpp_cb";
+
+const char CB_PRIVATE_MEMBERS[] =
+R"__cpp_cb(
+  void FilePayloadSend(std::string path, cion_peer_info_h peer);
+
+  static void OnConnectionResultCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_connection_result_h result,
+      void *user_data);
+  static void OnDisconnectedCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data);
+  static void OnConnectionRequestCB(const char *service_name,
+      const cion_peer_info_h peer_info, void *user_data);
+  static void OnDataReceivedCB(const char *service_name,
+      const cion_peer_info_h peer_info, const unsigned char *data,
+      unsigned int data_size, unsigned char **return_data,
+      unsigned int *return_data_size, void *user_data);
+  static void OnPayloadReceivedCB(const char *service_name,
+      const cion_peer_info_h peer_info, const cion_payload_h payload,
+      cion_payload_transfer_status_e status,
+      void *user_data);
+
+  std::shared_ptr<ServiceBase::Factory> service_factory_;
+  std::list<std::shared_ptr<ServiceBase>> services_;
+  cion_server_h cion_server_;
+)__cpp_cb";
+
+const char CB_SERVICE_BASE_FRONT[] =
+R"__cpp_cb(
+  class ServiceBase {
+   public:
+    class Factory {
+     public:
+      /// <summary>
+      /// The method for making service instances
+      /// </summary>
+      /// <param name="peer">The client peer info</param>
+      virtual std::shared_ptr<ServiceBase> CreateService(cion_peer_info_h peer) = 0;
+    };
+
+    virtual ~ServiceBase() = default;
+
+    /// <summary>
+    /// Gets peer info
+    /// </summary>
+    const cion_peer_info_h GetPeer() const {
+      return peer_;
+    }
+
+    /// <summary>
+    /// This method will be called when file receieved from client app
+    /// </summary>
+    virtual void OnFileReceived(cion_peer_info_h peer_info,
+        cion_payload_h file_payload, cion_payload_transfer_status_e status) = 0;
+
+    /// <summary>
+    /// This method will be called when the client is connection requested
+    /// </summary>
+    virtual void OnRequested(std::shared_ptr<ServiceBase> s) = 0;
+
+    /// <summary>
+    /// This method will be called when the client is connected
+    /// </summary>
+    virtual void OnCreate() = 0;
+
+    /// <summary>
+    /// This method will be called when the client is disconnected
+    /// </summary>
+    virtual void OnTerminate() = 0;
+
+    void Dispatch(rpc_port_h port, rpc_port_h callback_port,
+        rpc_port_parcel_h parcel, std::shared_ptr<ServiceBase> service);
+
+)__cpp_cb";
+
+const char CB_SERVICE_BASE_BACK[] =
+R"__cpp_cb(
+   protected:
+    ServiceBase(cion_peer_info_h peer);
+
+   private:
+    cion_peer_info_h peer_;
+    std::unique_ptr<ActiveObject> active_object_;
+  };)__cpp_cb";
+
+const char CB_PENDING_JOB[] =
+R"__cpp_cb(
+  class PendingJob : public Job, Job::IEvent {
+   public:
+    PendingJob(rpc_port_h port, rpc_port_h callback_port,
+        rpc_port_parcel_h parcel, std::shared_ptr<ServiceBase> service_);
+
+   private:
+    void Run() override;
+
+   private:
+    rpc_port_h port_;
+    rpc_port_h callback_port_;
+    rpc_port_parcel_h parcel_;
+    std::shared_ptr<ServiceBase> service_;
+  };
+)__cpp_cb";
+
+const char CB_PUBLIC_METHODS[] =
+R"__cpp_cb(  ##(const std::string& service_name, const std::string& display_name);
+  ~##();
+
+  /// <summary>
+  /// Listens to client apps
+  /// </summary>
+  /// <param name="service_factory">The factory object for making service instances</param>
+  /// <exception cref="InvalidIOException">
+  /// Thrown when internal I/O error happen.
+  /// </exception>
+  void Listen(std::shared_ptr<ServiceBase::Factory> service_factory);
+
+  /// <summary>
+  /// Accepts client apps
+  /// </summary>
+  void Accept(std::shared_ptr<ServiceBase> service);
+
+  /// <summary>
+  /// Rejects client apps
+  /// </summary>
+  void Reject(std::shared_ptr<ServiceBase> service, std::string reason);
+
+  /// <summary>
+  /// Disconnects client apps
+  /// </summary>
+  void Disconnect(std::shared_ptr<ServiceBase> service);
+
+  /// <summary>
+  /// Gets service objects which are connected
+  /// </summary>
+  /// <returns>The list of service objects which are connected</returns>
+  const std::list<std::shared_ptr<ServiceBase>>& GetServices() const {
+    return services_;
+  }
+
+)__cpp_cb";
+
+
+const char CB_JOB[] = R"__cls_job(class Job {
+ public:
+  class IEvent {
+   public:
+    virtual void Run() = 0;
+  };
+
+  Job() : handler_(nullptr) {
+  }
+
+  Job(IEvent* handler) : handler_(handler) {
+  }
+  virtual ~Job() = default;
+
+  Job(const Job& job) {
+    handler_ = job.handler_;
+  }
+
+  Job& operator = (const Job& job) {
+    if (this != &job)
+      handler_ = job.handler_;
+    return *this;
+  }
+  Job(Job&& job) noexcept {
+    handler_ = job.handler_;
+    job.handler_ = nullptr;
+  }
+
+  Job& operator = (Job&& job) noexcept {
+    if (this != &job) {
+      handler_ = job.handler_;
+      job.handler_ = nullptr;
+    }
+    return *this;
+  }
+
+  void Invoke() {
+    if (handler_)
+      handler_->Run();
+  }
+
+ private:
+  IEvent* handler_;
+};
+
+)__cls_job";
+
+const char CB_SHARED_QUEUE[] = R"__cls_shared_que(
+template <class T>
+class SharedQueue {
+ public:
+  SharedQueue() = default;
+  virtual ~SharedQueue() = default;
+
+  void Push(T item) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    queue_.push_back(item);
+    cond_var_.notify_one();
+  }
+
+  void PushFront(T item) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    queue_.push_front(item);
+    cond_var_.notify_one();
+  }
+
+  bool TryAndPop(T& item) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    if (queue_.empty())
+       return false;
+
+    item = queue_.front();
+    queue_.pop_front();
+
+    return true;
+  }
+
+  void WaitAndPop(T& item) {
+    std::unique_lock<std::mutex> lock(mutex_);
+    while (queue_.empty())
+      cond_var_.wait(lock);
+
+    item = queue_.front();
+    queue_.pop_front();
+  }
+
+  bool Empty() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return queue_.empty();
+  }
+
+  int Size() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return queue_.size();
+  }
+
+ private:
+  std::deque<T> queue_;
+  mutable std::mutex mutex_;
+  std::condition_variable cond_var_;
+};
+
+)__cls_shared_que";
+
+const char CB_ACTIVE_OBJECT[] = R"__cls_active_obj(class ActiveObject : public Job::IEvent {
+ public:
+  ActiveObject() {
+    thread_ = std::thread([&]{
+          do {
+            std::shared_ptr<Job> item;
+            queue_.WaitAndPop(item);
+            item->Invoke();
+          } while (!done_);
+        });
+  }
+  virtual ~ActiveObject() {
+    Quit();
+    thread_.join();
+  }
+
+ public:
+  void Send(std::shared_ptr<Job> job) {
+    queue_.Push(std::move(job));
+  }
+
+ private:
+  void Quit() {
+    Send(std::shared_ptr<Job>(new (std::nothrow) Job(this)));
+  }
+  void Run() override {
+    done_ = true;
+  }
+
+ private:
+  std::thread thread_;
+  bool done_ = false;
+  SharedQueue<std::shared_ptr<Job>> queue_;
+};
+
+)__cls_active_obj";
+
+const char CB_HEADER[] =
+R"__cpp_cb(
+#pragma once
+
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+#include <cion.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <list>
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <deque>
+#include <thread>
+
+)__cpp_cb";
+
+#endif  // IDLC_CPP_CION_GEN_CPP_STUB_HEADER_GEN_CB_H_
index 6020d65ac98a26e95a3d48b8197b0b5ba406ece7..5b9c4fe2884e267851da2dae2f1819ca367b4060 100644 (file)
 #include "idlc/gen_cion/c_cion_stub_body_gen.h"
 #include "idlc/gen_cion/cs_cion_proxy_gen.h"
 #include "idlc/gen_cion/cs_cion_stub_gen.h"
-
+#include "idlc/gen_cion/cpp_cion_proxy_header_gen.h"
+#include "idlc/gen_cion/cpp_cion_proxy_body_gen.h"
+#include "idlc/gen_cion/cpp_cion_stub_header_gen.h"
+#include "idlc/gen_cion/cpp_cion_stub_body_gen.h"
 #include "idlc/options.h"
 
 void GenerateStubCodes(std::shared_ptr<tidl::Options> options,
@@ -57,7 +60,13 @@ void GenerateStubCodes(std::shared_ptr<tidl::Options> options,
       break;
     }
     case tidl::Options::LANGUAGE_TYPE_CPP:
+    {
+      tidl::CppCionStubHeaderGen stub_header(ps.GetDoc(), options);
+      stub_header.Run(options->GetOutput() + ".h");
+      tidl::CppCionStubBodyGen stub_body(ps.GetDoc(), options);
+      stub_body.Run(options->GetOutput() + ".cc");
       break;
+    }
     case tidl::Options::LANGUAGE_TYPE_CSHARP:
     {
        tidl::CsCionStubGen stub(ps.GetDoc());
@@ -126,6 +135,13 @@ void GenerateProxyCodes(std::shared_ptr<tidl::Options> options,
       break;
     }
     case tidl::Options::LANGUAGE_TYPE_CPP:
+    {
+      tidl::CppCionProxyHeaderGen proxy_header(ps.GetDoc());
+      proxy_header.Run(options->GetOutput() + ".h");
+      tidl::CppCionProxyBodyGen proxy_body(ps.GetDoc());
+      proxy_body.Run(options->GetOutput() + ".cc");
+      break;
+    }
       break;
     case tidl::Options::LANGUAGE_TYPE_CSHARP:
     {