Implement C++ Group Generator 50/296450/9
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 28 Jul 2023 04:05:13 +0000 (13:05 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 7 Aug 2023 01:34:54 +0000 (10:34 +0900)
This is for protocol verion 2. Marshaling type info feature is added.

Change-Id: If32a2a884241a509f14d6c133feab25ef6ce613b
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
idlc/gen/version2/cpp_generator_base.cc
idlc/gen/version2/cpp_generator_base.hh
idlc/gen/version2/cpp_group_body_generator.cc [new file with mode: 0644]
idlc/gen/version2/cpp_group_body_generator.hh [new file with mode: 0644]
idlc/gen/version2/cpp_group_body_generator_cb.hh [new file with mode: 0644]
idlc/gen/version2/cpp_group_header_generator.cc [new file with mode: 0644]
idlc/gen/version2/cpp_group_header_generator.hh [new file with mode: 0644]
idlc/gen/version2/cpp_group_header_generator_cb.hh [new file with mode: 0644]
idlc/main.cc

index ca41e7a..50b1881 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <sstream>
 #include <utility>
+#include <vector>
 
 #include "idlc/gen/version2/cpp_generator_base_cb.hh"
 
@@ -273,11 +274,13 @@ std::string CppGeneratorBase::GetParameters(const Parameters& params) {
   return code;
 }
 
-std::string CppGeneratorBase::GenStructuresForHeader() {
+std::string CppGeneratorBase::GenStructuresForHeader(bool use_file) {
   std::string code(CB_HEADER_BUNDLE);
   code += NLine(1);
-  code += CB_HEADER_FILE;
-  code += NLine(1);
+  if (use_file) {
+    code += CB_HEADER_FILE;
+    code += NLine(1);
+  }
   for (auto& block : GetDocument().GetBlocks()) {
     if (block->GetType() != Block::TYPE_STRUCTURE)
       continue;
@@ -295,8 +298,9 @@ std::string CppGeneratorBase::GenStructureForHeader(const Structure& st) {
           .Change("<CLS_NAME>", st.GetID())
           .Change("<PARAMS>", GenParameters(st.GetElements()))
           .Change("<GETTER_SETTER>",
-              GenStructureGetterSetterForHeader(st.GetElements()))
-          .Change("<MEMBERS>", GenStructureMembersForHeader(st.GetElements())));
+                  GenStructureGetterSetterForHeader(st.GetElements()))
+          .Change("<MEMBERS>\n",
+                  GenStructureMembersForHeader(st.GetElements())));
 }
 
 std::string CppGeneratorBase::GenStructureGetterSetterForHeader(
@@ -417,9 +421,11 @@ std::string CppGeneratorBase::Trim(std::string str) {
   return str.substr(first, (last - first + 1));
 }
 
-std::string CppGeneratorBase::GenStructures() {
+std::string CppGeneratorBase::GenStructures(bool use_file) {
   std::string code(CB_BODY_BUNDLE);
-  code += CB_BODY_FILE;
+  if (use_file)
+    code += CB_BODY_FILE;
+
   for (auto& block : GetDocument().GetBlocks()) {
     if (block->GetType() == Block::Type::TYPE_STRUCTURE) {
       auto& st = static_cast<const Structure&>(*block);
@@ -473,12 +479,13 @@ std::string CppGeneratorBase::GetSetterValue(const BaseType& type,
   return IsObject(type) ? "std::move(" + value + ")" : value;
 }
 
-void CppGeneratorBase::InitUnitTypes() {
+void CppGeneratorBase::InitUnitTypes(bool use_file) {
   AddUnitType("int", BaseType("int", ""));
   AddUnitType("bool", BaseType("bool", ""));
   AddUnitType("string", BaseType("string", ""));
   AddUnitType("bundle", BaseType("bundle", ""));
-  AddUnitType("file", BaseType("file", ""));
+  if (use_file)
+    AddUnitType("file", BaseType("file", ""));
 
   for (auto& block : GetDocument().GetBlocks()) {
     if (block->GetType() == Block::TYPE_INTERFACE) {
@@ -515,8 +522,8 @@ void CppGeneratorBase::AddUnitType(std::string name, BaseType type) {
   unit_types_[std::move(name)] = std::move(type);
 }
 
-std::string CppGeneratorBase::GenUnitMap() {
-  InitUnitTypes();
+std::string CppGeneratorBase::GenUnitMap(bool use_file) {
+  InitUnitTypes(use_file);
   std::string code = GenUnit();
   code += ReplaceAll(CB_UNIT_MAP)
       .Change("<UNIT_MAP_READ_WRITE>", GenUnitMapReadWrite());
index 93da3cd..7ca4d09 100644 (file)
@@ -41,7 +41,7 @@ class CppGeneratorBase : public tidl::Generator {
   void GenVersionDefinition(std::ofstream& stream);
 
   std::string GenExceptions();
-  std::string GenStructuresForHeader();
+  std::string GenStructuresForHeader(bool use_file = true);
   std::string GenMethodIds(const Interface& iface);
   std::string GenDelegateIds(const Interface& iface);
   std::string GenParameters(const Elements& elms);
@@ -55,9 +55,9 @@ class CppGeneratorBase : public tidl::Generator {
   std::string GetParameterType(const BaseType& type);
   std::string GetParameters(const Parameters& params);
   std::string SmartIndent(const std::string& str);
-  std::string GenStructures();
+  std::string GenStructures(bool use_file = true);
   std::string GetSetterValue(const BaseType& type, const std::string& value);
-  std::string GenUnitMap();
+  std::string GenUnitMap(bool use_file = true);
   std::string GenPrivateSharing(const Parameter& param);
   std::string GetSettingInitValue(const BaseType& type);
 
@@ -68,7 +68,7 @@ class CppGeneratorBase : public tidl::Generator {
   std::string GenStructure(const Structure& st);
   std::string GenStructureMemberInit(const Elements& elms);
   std::string GenStructureGetterSetter(const Structure& st);
-  void InitUnitTypes();
+  void InitUnitTypes(bool use_file);
   void AddUnitType(std::string name, BaseType type);
   std::string GenUnitMapReadWrite();
   std::string GenUnit();
diff --git a/idlc/gen/version2/cpp_group_body_generator.cc b/idlc/gen/version2/cpp_group_body_generator.cc
new file mode 100644 (file)
index 0000000..7f1c5ab
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2023 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/version2/cpp_group_body_generator.hh"
+
+#include <utility>
+
+#include "idlc/gen/version2/cpp_group_body_generator_cb.hh"
+
+namespace tidl {
+namespace version2 {
+
+CppGroupBodyGenerator::CppGroupBodyGenerator(std::shared_ptr<Document> doc)
+    : CppGeneratorBase(std::move(doc)) {}
+
+void CppGroupBodyGenerator::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  GenHeader(stream);
+  GenLogTag(stream, "RPC_PORT_GROUP");
+  GenLogDefinition(stream);
+  GenVersionDefinition(stream);
+  GenNamespace(stream);
+}
+
+void CppGroupBodyGenerator::OnFiniGen(std::ofstream& stream) {}
+
+void CppGroupBodyGenerator::GenHeader(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");
+
+  ReplaceAll(CB_HEADER).Change("<HEADER_FILE>", header_file).Out(stream);
+}
+
+void CppGroupBodyGenerator::GenNamespace(std::ofstream& stream) {
+  ReplaceAll(CB_NAMESPACE)
+      .ChangeToLower("<FILE_NAMESPACE>", GetFileNamespace())
+      .Change("<STRUCTURES>", GenStructures(false))
+      .Change("<UNIT_MAP>", GenUnitMap(false))
+      .Change("<INTERFACES>", GenInterfaces())
+      .Transform([&](std::string str) { return SmartIndent(str); })
+      .Out(stream);
+}
+
+std::string CppGroupBodyGenerator::GenInterfaces() {
+  std::string code;
+  for (auto& block : GetDocument().GetBlocks()) {
+    if (block->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& iface = static_cast<const Interface&>(*block);
+    code += GenInterface(iface);
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CppGroupBodyGenerator::GenInterface(const Interface& iface) {
+  return std::string(
+      ReplaceAll(CB_INTERFACE)
+          .Change("<CLS_NAME>", iface.GetID())
+          .Change("<IMPL_DISPATCH_FUNC_INIT>\n",
+              GenInterfaceImplDispatchFuncInit(iface))
+          .Change("<IMPL_METHOD>", GenInterfaceMethod(iface))
+          .Change("<IMPL_DISPATCH_FUNC>", GenInterfaceImplDispatchFunc(iface)));
+}
+
+std::string CppGroupBodyGenerator::GenInterfaceImplDispatchFuncInit(
+    const Interface& iface) {
+  std::string code;
+  for (auto& decl : iface.GetDeclarations()) {
+    code += ReplaceAll(CB_INTERFACE_IMPL_DISPATCH_FUNC_INIT)
+        .Change("<NAME>", decl->GetID())
+        .Change("<CLS_NAME>", iface.GetID());
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CppGroupBodyGenerator::GenInterfaceImplDispatchFunc(
+    const Interface& iface) {
+  std::string code;
+  for (auto& decl : iface.GetDeclarations()) {
+    code += ReplaceAll(CB_INTERFACE_DISPATCH_FUNC)
+        .Change("<CLS_NAME>", iface.GetID())
+        .Change("<DESERIALIZE>", GenInterfaceImplDispatchFuncDeserialize(*decl))
+        .Change("<NAME>", decl->GetID())
+        .Change("<PARAMS>", GenInterfaceImplDispatchFuncParams(*decl));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CppGroupBodyGenerator::GenInterfaceImplDispatchFuncDeserialize(
+    const Declaration& decl) {
+  std::string code;
+  for (auto& param : decl.GetParameters()) {
+    auto& type = param->GetParameterType().GetBaseType();
+    std::string str = std::string(
+        ReplaceAll(CB_INTERFACE_DISPATCH_FUNC_UNIT_MAP_READ)
+        .Change("<TYPE>", ConvertTypeToString(type))
+        .Change("<NAME>", param->GetID()));
+    code += RemoveLine(str);
+  }
+
+  return code;
+}
+
+std::string CppGroupBodyGenerator::GenInterfaceImplDispatchFuncParams(
+    const Declaration& decl) {
+  std::string code;
+  for (auto& param : decl.GetParameters()) {
+    if (!code.empty())
+      code += ", ";
+
+    code += param->GetID();
+  }
+
+  return code;
+}
+
+std::string CppGroupBodyGenerator::GenInterfaceMethod(const Interface& iface) {
+  std::string code;
+  for (auto& decl : iface.GetDeclarations()) {
+    code += ReplaceAll(CB_INTERFACE_METHOD)
+        .Change("<CLS_NAME>", iface.GetID())
+        .Change("<NAME>", decl->GetID())
+        .Change("<PARAMS>", GetParameters(decl->GetParameters()))
+        .Change("<SERIALIZE>", GenInterfaceMethodSerialize(*decl));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CppGroupBodyGenerator::GenInterfaceMethodSerialize(
+    const Declaration& decl) {
+  std::string code;
+  for (auto& param : decl.GetParameters()) {
+    code += ReplaceAll(CB_INTERFACE_METHOD_UNIT_MAP_WRITE)
+        .Change("<NAME>", param->GetID());
+  }
+
+  return RemoveLine(code);
+}
+
+}  // namespace version2
+}  // namespace tidl
diff --git a/idlc/gen/version2/cpp_group_body_generator.hh b/idlc/gen/version2/cpp_group_body_generator.hh
new file mode 100644 (file)
index 0000000..86a38c4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 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_GEN_VERSION2_CPP_GROUP_BODY_GENERATOR_HH_
+#define IDLC_GEN_VERSION2_CPP_GROUP_BODY_GENERATOR_HH_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen/version2/cpp_generator_base.hh"
+
+namespace tidl {
+namespace version2 {
+
+class CppGroupBodyGenerator : public CppGeneratorBase {
+ public:
+  explicit CppGroupBodyGenerator(std::shared_ptr<Document> doc);
+  virtual ~CppGroupBodyGenerator() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenHeader(std::ofstream& stream);
+  void GenNamespace(std::ofstream& stream);
+  std::string GenInterfaces();
+  std::string GenInterface(const Interface& iface);
+  std::string GenInterfaceImplDispatchFuncInit(const Interface& iface);
+  std::string GenInterfaceImplDispatchFunc(const Interface& iface);
+  std::string GenInterfaceImplDispatchFuncDeserialize(const Declaration& iface);
+  std::string GenInterfaceImplDispatchFuncParams(const Declaration& iface);
+  std::string GenInterfaceMethod(const Interface& iface);
+  std::string GenInterfaceMethodSerialize(const Declaration& decl);
+};
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_CPP_GROUP_BODY_GENERATOR_HH_
diff --git a/idlc/gen/version2/cpp_group_body_generator_cb.hh b/idlc/gen/version2/cpp_group_body_generator_cb.hh
new file mode 100644 (file)
index 0000000..bd39a1b
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2023 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_GEN_VERSION2_CPP_GROUP_BODY_GENERATOR_CB_HH_
+#define IDLC_GEN_VERSION2_CPP_GROUP_BODY_GENERATOR_CB_HH_
+
+namespace tidl {
+namespace version2 {
+
+/**
+ * <HEADER_FILE> The header file name.
+ */
+constexpr const char CB_HEADER[] =
+R"__cpp_cb(
+#include "<HEADER_FILE>"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <dlog.h>
+
+#include <climits>
+)__cpp_cb";
+
+/**
+ * <FILE_NAMESPACE> The namespace of the file.
+ * <STRCUTURES> The implementation of structures.
+ * <UNIT_MAP> The implementation of unit map.
+ * <INTERFACES> The implementation of interfaces.
+ */
+constexpr const char CB_NAMESPACE[] =
+R"__cpp_cb(
+namespace rpc_port {
+namespace <FILE_NAMESPACE> {
+
+<STRUCTURES>
+namespace group {
+
+<UNIT_MAP>
+<INTERFACES>
+}  // namespace group
+}  // namespace <FILE_NAMESPACE>
+}  // namespace rpc_port
+)__cpp_cb";
+
+/**
+ * <CLS_NAME> The interface name.
+ * <IMPL_DISPATCH_FUNC_INIT> The implementation of the initialization of dispatch funcs.
+ * <IMPL_DISPATCH_FUNC> The implementation of dispatch funcs of methods.
+ * <IMPL_METHOD> The implementation of methods.
+ */
+constexpr const char CB_INTERFACE[] =
+R"__cpp_cb(
+<CLS_NAME>::<CLS_NAME>(std::string sender_appid, bool is_system) : sender_appid_(std::move(sender_appid)), is_system_(is_system) {
+  dispatch_funcs_ = {
+    <IMPL_DISPATCH_FUNC_INIT>
+  };
+
+  Subscribe();
+}
+
+<CLS_NAME>::~<CLS_NAME>() { Unsubscribe(); }
+
+void <CLS_NAME>::Subscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_add_event_handler(GetEventName().c_str(), EventCb, this, &event_handler_);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to register events. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void <CLS_NAME>::Unsubscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  if (event_handler_) {
+    event_remove_event_handler(event_handler_);
+    event_handler_ = nullptr;
+  }
+}
+
+bundle* <CLS_NAME>::GetBundleFromParcel(rpc_port_parcel_h parcel) {
+  void* raw = nullptr;
+  unsigned int size = 0;
+  int ret = rpc_port_parcel_get_raw(parcel, &raw, &size);
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  bundle* b = bundle_create();
+  if (b == nullptr)
+    return nullptr;
+
+  ret = bundle_add_byte(b, "TIDL_RAW", raw, size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  return b;
+}
+
+rpc_port_parcel_h <CLS_NAME>::GetParcelFromBundle(bundle* b) {
+  void* raw = nullptr;
+  size_t size = 0;
+  int ret = bundle_get_byte(b, "TIDL_RAW", &raw, &size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  rpc_port_parcel_h parcel;
+  ret = rpc_port_parcel_create_from_raw(&parcel, raw, static_cast<unsigned int>(size));
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  return parcel;
+}
+
+std::string <CLS_NAME>::GetEventName() {
+  if (is_system_)
+    return "tizen.system.event.tidl_iface_<CLS_NAME>";
+
+  return "event." + sender_appid_ + ".tidl_iface_<CLS_NAME>";
+}
+
+void <CLS_NAME>::EventCb(const char* event_name, bundle* event_data, void* user_data) {
+  auto* handle = static_cast<<CLS_NAME>*>(user_data);
+  rpc_port_parcel_h parcel = handle->GetParcelFromBundle(event_data);
+  if (parcel == nullptr) {
+    _E("Invalid bundle");
+    return;
+  }
+
+  UnitMap unit_map;
+  unit_map.Deserialize(parcel);
+  rpc_port_parcel_destroy(parcel);
+
+  int cmd = -1;
+  unit_map.Read("[METHOD]", cmd);
+
+  auto found = handle->dispatch_funcs_.find(cmd);
+  if (found == handle->dispatch_funcs_.end()) {
+    _E("Unknown command(%d)", cmd);
+    return;
+  }
+
+  auto& func = found->second;
+  func(unit_map);
+}
+
+<IMPL_METHOD>
+<IMPL_DISPATCH_FUNC>
+)__cpp_cb";
+
+/**
+ * <NAME> The method name of the interface.
+ * <CLS_NAME> The interface name.
+ */
+constexpr const char CB_INTERFACE_IMPL_DISPATCH_FUNC_INIT[] =
+R"__cpp_cb(
+{ static_cast<int>(MethodId::<NAME>), std::bind(&<CLS_NAME>::Dispatch<NAME>, this, std::placeholders::_1) },
+)__cpp_cb";
+
+/**
+ * <CLS_NAME> The interface name.
+ * <NAME> The method name.
+ * <DESERIALIZE> The deserialize parameters of the method.
+ * <PARAMS> The parameters of the method.
+ */
+constexpr const char CB_INTERFACE_DISPATCH_FUNC[] =
+R"__cpp_cb(
+void <CLS_NAME>::Dispatch<NAME>(const UnitMap& unit_map) {
+  <DESERIALIZE>
+  On<NAME>(<PARAMS>);
+}
+)__cpp_cb";
+
+/**
+ * <TYPE> The parameter type.
+ * <NAME> The parameter name.
+ */
+constexpr const char CB_INTERFACE_DISPATCH_FUNC_UNIT_MAP_READ[] =
+R"__cpp_cb(
+<TYPE> <NAME>;
+unit_map.Read("<NAME>", <NAME>);
+)__cpp_cb";
+
+/**
+ * <CLS_NAME> The interface name.
+ * <NAME> The method name of the interface.
+ * <PARAMS> The parameters of the method.
+ * <SERIALIZE> The implmenetation of the serialization of parameters.
+ */
+constexpr const char CB_INTERFACE_METHOD[] =
+R"__cpp_cb(
+void <CLS_NAME>::<NAME>(<PARAMS>) {
+  UnitMap unit_map;
+  unit_map.Write("[METHOD]", static_cast<int>(MethodId::<NAME>));
+  <SERIALIZE>
+  rpc_port_parcel_h parcel = nullptr;
+  rpc_port_parcel_create(&parcel);
+  unit_map.Serialize(parcel);
+  bundle* b = GetBundleFromParcel(parcel);
+  rpc_port_parcel_destroy(parcel);
+  if (b == nullptr) {
+    _E("Failed to make bundle from parcel");
+    throw InvalidIOException();
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_publish_app_event(GetEventName().c_str(), b);
+  bundle_free(b);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to publish event. error(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+)__cpp_cb";
+
+/**
+ * <NAME> The parameter name.
+ */
+constexpr const char CB_INTERFACE_METHOD_UNIT_MAP_WRITE[] =
+R"__cpp_cb(
+unit_map.Write("<NAME>", <NAME>);
+)__cpp_cb";
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_CPP_GROUP_BODY_GENERATOR_CB_HH_
diff --git a/idlc/gen/version2/cpp_group_header_generator.cc b/idlc/gen/version2/cpp_group_header_generator.cc
new file mode 100644 (file)
index 0000000..2ceff36
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 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/version2/cpp_group_header_generator.hh"
+
+#include <utility>
+
+#include "idlc/gen/version2/cpp_group_header_generator_cb.hh"
+
+namespace tidl {
+namespace version2 {
+
+CppGroupHeaderGenerator::CppGroupHeaderGenerator(std::shared_ptr<Document> doc)
+    : CppGeneratorBase(std::move(doc)) {}
+
+void CppGroupHeaderGenerator::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  stream << CB_HEADER;
+  GenNamespace(stream);
+}
+
+void CppGroupHeaderGenerator::OnFiniGen(std::ofstream& stream) {}
+
+void CppGroupHeaderGenerator::GenNamespace(std::ofstream& stream) {
+  ReplaceAll(CB_NAMESPACE)
+      .ChangeToLower("<FILE_NAMESPACE>", GetFileNamespace())
+      .Change("<STRUCTURES>", GenStructuresForHeader(false))
+      .Change("<EXCEPTIONS>", GenExceptions())
+      .Change("<INTERFACES>", GenInterfaces())
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
+}
+
+std::string CppGroupHeaderGenerator::GenInterfaces() {
+  std::string code;
+  for (auto& block : GetDocument().GetBlocks()) {
+    if (block->GetType() != Block::Type::TYPE_INTERFACE)
+      continue;
+
+    auto& iface = static_cast<const Interface&>(*block);
+    code += GenInterface(iface);
+    code += NLine(1);
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CppGroupHeaderGenerator::GenInterface(const Interface& iface) {
+  return std::string(
+      ReplaceAll(CB_INTERFACE)
+          .Change("<CLS_NAME>", iface.GetID())
+          .Change("<PUBLIC_MEMBERS>", GenInterfacePublicMembers(iface))
+          .Change("<PRIVATE_MEMBERS>", GenInterfacePrivateMembers(iface)));
+}
+
+std::string CppGroupHeaderGenerator::GenInterfacePublicMembers(
+    const Interface& iface) {
+  std::string code;
+  for (auto& decl : iface.GetDeclarations()) {
+    code += ReplaceAll(CB_METHOD)
+        .Change("<NAME>", decl->GetID())
+        .Change("<PARAMS>", GetParameters(decl->GetParameters()));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CppGroupHeaderGenerator::GenInterfacePrivateMembers(
+    const Interface& iface) {
+  std::string code = GenMethodIds(iface);
+  for (auto& decl : iface.GetDeclarations()) {
+    code += ReplaceAll(CB_DISPATCH_FUNC)
+        .Change("<NAME>", decl->GetID());
+  }
+
+  return code;
+}
+
+}  // namespace version2
+}  // namespace tidl
diff --git a/idlc/gen/version2/cpp_group_header_generator.hh b/idlc/gen/version2/cpp_group_header_generator.hh
new file mode 100644 (file)
index 0000000..4469f8f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 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_GEN_VERSION2_CPP_GROUP_HEADER_GENERATOR_HH_
+#define IDLC_GEN_VERSION2_CPP_GROUP_HEADER_GENERATOR_HH_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen/version2/cpp_generator_base.hh"
+
+namespace tidl {
+namespace version2 {
+
+class CppGroupHeaderGenerator : public CppGeneratorBase {
+ public:
+  explicit CppGroupHeaderGenerator(std::shared_ptr<Document> doc);
+  virtual ~CppGroupHeaderGenerator() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenNamespace(std::ofstream& stream);
+  std::string GenInterfaces();
+  std::string GenInterface(const Interface& iface);
+  std::string GenInterfacePublicMembers(const Interface& iface);
+  std::string GenInterfacePrivateMembers(const Interface& iface);
+};
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_CPP_GROUP_HEADER_GENERATOR_HH_
diff --git a/idlc/gen/version2/cpp_group_header_generator_cb.hh b/idlc/gen/version2/cpp_group_header_generator_cb.hh
new file mode 100644 (file)
index 0000000..406c078
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2023 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_GEN_VERSION2_CPP_GROUP_HEADER_GENERATOR_CB_HH_
+#define IDLC_GEN_VERSION2_CPP_GROUP_HEADER_GENERATOR_CB_HH_
+
+namespace tidl {
+namespace version2 {
+
+constexpr const char CB_HEADER[] =
+R"__cpp_cb(
+#pragma once
+
+#include <app_event.h>
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+
+#include <atomic>
+#include <list>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+#include <unordered_map>
+)__cpp_cb";
+
+/**
+ * <FILE_NAMESPACE> The namespace of the file.
+ * <STRCUTURES> The structure definitions.
+ * <EXCEPTIONS> The exceptions.
+ * <INTERFACES> The interface definitions.
+ */
+constexpr const char CB_NAMESPACE[] =
+R"__cpp_cb(
+namespace rpc_port {
+namespace <FILE_NAMESPACE> {
+
+<STRUCTURES>
+namespace group {
+
+<EXCEPTIONS>
+<INTERFACES>
+}  // namespace group
+}  // namespace <FILE_NAMESPACE>
+}  // namespace rpc_port
+)__cpp_cb";
+
+/**
+ * <CLS_NAME> The class name of the interface.
+ * <PUBLIC_MEMBERS> The implementation of public members of the interface.
+ * <PRIVATE_MEMBERS> The implementation of private members of the interface.
+ */
+constexpr const char CB_INTERFACE[] =
+R"__cpp_cb(
+class <CLS_NAME> {
+ public:
+  <CLS_NAME>(std::string sender_appid, bool is_system = false);
+  virtual ~<CLS_NAME>();
+
+  <PUBLIC_MEMBERS>
+
+ private:
+  using DispatchFunc = std::function<void(const UnitMap& unit_map)>;
+
+  <PRIVATE_MEMBERS>
+
+  bundle* GetBundleFromParcel(rpc_port_parcel_h parcel);
+  rpc_port_parcel_h GetParcelFromBundle(bundle* b);
+  std::string GetEventName();
+  void Subscribe();
+  void Unsubscribe();
+  static void EventCb(const char* event_name, bundle* event_data, void* user_data);
+
+ private:
+  event_handler_h event_handler_ = nullptr;
+  std::string sender_appid_;
+  std::recursive_mutex mutex_;
+  bool is_system_;
+  std::unordered_map<int, DispatchFunc> dispatch_funcs_;
+};
+)__cpp_cb";
+
+/**
+ * <NAME> The method name.
+ * <PARAMS> The parameters of the method.
+ */
+constexpr const char CB_METHOD[] =
+R"__cpp_cb(
+void <NAME>(<PARAMS>);
+virtual void On<NAME>(<PARAMS>) {}
+)__cpp_cb";
+
+/**
+ * <NAME> The method name.
+ */
+constexpr const char CB_DISPATCH_FUNC[] =
+R"__cpp_cb(
+void Dispatch<NAME>(const UnitMap& unit_map);
+)__cpp_cb";
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_CPP_GROUP_HEADER_GENERATOR_CB_HH_
index 9e0bd9c..5f3a97d 100644 (file)
@@ -51,6 +51,8 @@
 #include "idlc/gen/version2/cs_proxy_generator.h"
 #include "idlc/gen/version2/cs_stub_generator.h"
 #include "idlc/gen/version2/cs_group_generator.h"
+#include "idlc/gen/version2/cpp_group_body_generator.hh"
+#include "idlc/gen/version2/cpp_group_header_generator.hh"
 #include "idlc/gen_cion/c_cion_proxy_header_gen.h"
 #include "idlc/gen_cion/c_cion_proxy_body_gen.h"
 #include "idlc/gen_cion/c_cion_stub_header_gen.h"
@@ -741,10 +743,17 @@ void GenerateGroupCodes(std::shared_ptr<tidl::Options> options,
     switch (options->GetLanguage()) {
     case tidl::Options::LANGUAGE_TYPE_CPP:
     {
-      tidl::CppGroupHeaderGen group_header(ps.GetDoc());
-      group_header.Run(options->GetOutput() + ".h");
-      tidl::CppGroupBodyGen group_body(ps.GetDoc());
-      group_body.Run(options->GetOutput() + ".cc");
+      if (ps.GetVersion() == 2) {
+        tidl::version2::CppGroupHeaderGenerator group_header(ps.GetDoc());
+        group_header.Run(options->GetOutput() + ".h");
+        tidl::version2::CppGroupBodyGenerator group_body(ps.GetDoc());
+        group_body.Run(options->GetOutput() + ".cc");
+      } else {
+        tidl::CppGroupHeaderGen group_header(ps.GetDoc());
+        group_header.Run(options->GetOutput() + ".h");
+        tidl::CppGroupBodyGen group_body(ps.GetDoc());
+        group_body.Run(options->GetOutput() + ".cc");
+      }
       break;
     }
 
@@ -778,7 +787,6 @@ void GenerateGroupCodes(std::shared_ptr<tidl::Options> options,
         group.Run(options->GetOutput() + ".cs");
         break;
       }
-
     }
 
     default: