Refactor C Generator 64/261764/52
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 18 Aug 2021 06:54:24 +0000 (15:54 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 26 Aug 2021 07:13:29 +0000 (16:13 +0900)
- Fixes code block for readability
- Fixes some APIs to support container type
- Adds new APIs for consistency with C++ Generator
- Renames the APIs
- Adds annotations to functions of header files.

Change-Id: I3a7afb069d80985f88562a0ef1b3ce07229440dc
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
26 files changed:
idlc/CMakeLists.txt
idlc/gen/c_body_gen_array_base_cb.h [new file with mode: 0644]
idlc/gen/c_body_gen_base.cc
idlc/gen/c_body_gen_base.h
idlc/gen/c_body_gen_base_cb.h
idlc/gen/c_body_gen_list_base_cb.h [new file with mode: 0644]
idlc/gen/c_gen_base.cc
idlc/gen/c_gen_base.h
idlc/gen/c_gen_base_cb.h
idlc/gen/c_header_gen_base.cc
idlc/gen/c_header_gen_base.h
idlc/gen/c_header_gen_base_cb.h
idlc/gen/c_proxy_body_gen.cc
idlc/gen/c_proxy_body_gen.h
idlc/gen/c_proxy_body_gen_cb.h
idlc/gen/c_proxy_header_gen.cc
idlc/gen/c_proxy_header_gen.h
idlc/gen/c_proxy_header_gen_cb.h
idlc/gen/c_stub_body_gen.cc
idlc/gen/c_stub_body_gen.h
idlc/gen/c_stub_body_gen_cb.h
idlc/gen/c_stub_header_gen.cc
idlc/gen/c_stub_header_gen.h
idlc/gen/c_stub_header_gen_cb.h
idlc/gen/generator.h
idlc/main.cc

index 6b3f69f..375f58d 100644 (file)
@@ -17,7 +17,7 @@ ENDIF(DEFINED BUILD_WIN)
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wno-unused-function -Wno-sign-compare")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++14")
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc")
 SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
diff --git a/idlc/gen/c_body_gen_array_base_cb.h b/idlc/gen/c_body_gen_array_base_cb.h
new file mode 100644 (file)
index 0000000..e152a7d
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * 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_C_GEN_C_BODY_GEN_ARRAY_BASE_CB_H_
+#define IDLC_C_GEN_C_BODY_GEN_ARRAY_BASE_CB_H_
+
+/**
+ * <PREFIX> The prefix of the array structure.
+ * <NAME> The name of the array structure.
+ * <ELEMENT_TYPE> The type of the element of the array.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  <ELEMENT_TYPE>*value;
+  int size;
+} <PREFIX>_<NAME>_t;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the array structure.
+ * <NAME> The name of the array structure.
+ * <PARCEL_WRITE> The implementation to write the value to the parcel.
+ * <PARCEL_READ> The implemention to read the value from the parcel.
+ * <PARAM_TYPE_IN> The type of the input parameter.
+ * <PARAM_TYPE_OUT> The type of the output parameter.
+ * <ELEMENT_TYPE> The type of the element of the array.
+ * <ELEMENT_TYPE_SIZE> The size of the type of the element.
+ * <ELEMENTS_FREE> The implementation to release elements.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_BASE[] =
+R"__c_cb(
+static void __<PREFIX>_<NAME>_to(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  int i;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
+
+  rpc_port_parcel_write_array_count(parcel, h->size);
+
+  for (i = 0; i < h->size; ++i)
+    <PARCEL_WRITE>
+}
+
+static void __<PREFIX>_<NAME>_from(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  <ELEMENT_TYPE>value;
+  int ret;
+  int i;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  ret = rpc_port_parcel_read_array_count(parcel, &h->size);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read array count. error(%d)", ret);
+    set_last_result(ret);
+    return;
+  }
+
+  h->value = calloc(h->size, sizeof(<ELEMENT_TYPE_SIZE>));
+  if (h->value == nullptr) {
+    _E("Out of memory");
+    set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  for (i = 0; i < h->size; ++i) {
+    <PARCEL_READ>
+  }
+
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h)
+{
+  <PREFIX>_<NAME>_t *handle;
+
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->parcelable.to = __<PREFIX>_<NAME>_to;
+  handle->parcelable.from = __<PREFIX>_<NAME>_from;
+
+  *h = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h)
+{
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <ELEMENTS_FREE>
+
+  free(h);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone)
+{
+  <PREFIX>_<NAME>_h handle;
+  rpc_port_parcel_h parcel;
+  int ret;
+
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = <PREFIX>_<NAME>_create(&handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    return ret;
+  }
+
+  ret = rpc_port_parcel_create(&parcel);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  rpc_port_parcel_write(parcel, &h->parcelable, h);
+  rpc_port_parcel_read(parcel, &handle->parcelable, handle);
+  ret = get_last_result();
+  rpc_port_parcel_destroy(parcel);
+
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read data. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  *clone = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_set(<PREFIX>_<NAME>_h h, <PARAM_TYPE_IN>*value, int size)
+{
+  <PREFIX>_<NAME>_h handle;
+  <PREFIX>_<NAME>_h clone;
+  int ret;
+
+  if (h == nullptr || value == nullptr || size <= 0) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = <PREFIX>_<NAME>_create(&handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    return ret;
+  }
+
+  handle->value = (<ELEMENT_TYPE>*)value;
+  handle->size = size;
+
+  ret = <PREFIX>_<NAME>_clone(handle, &clone);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to clone handle. error(%d)", ret);
+    handle->value = nullptr;
+    handle->size = 0;
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  handle->value = h->value;
+  handle->size = h->size;
+  <PREFIX>_<NAME>_destroy(handle);
+
+  h->value = clone->value;
+  h->size = clone->size;
+
+  clone->value = nullptr;
+  clone->size = 0;
+  <PREFIX>_<NAME>_destroy(clone);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_get(<PREFIX>_<NAME>_h h, <PARAM_TYPE_OUT>*value, int *size)
+{
+  <PREFIX>_<NAME>_h handle;
+  int ret;
+
+  if (h == nullptr || value == nullptr || size == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = <PREFIX>_<NAME>_clone(h, &handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to clone handle. error(%d)", ret);
+    return ret;
+  }
+
+  *value = handle->value;
+  *size = handle->size;
+
+  handle->value = nullptr;
+  handle->size = 0;
+  <PREFIX>_<NAME>_destroy(handle);
+
+  return RPC_PORT_ERROR_NONE;
+}
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write(parcel, &h->value[i]->parcelable, h->value[i]);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_bundle(parcel, h->value[i]);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_STRING_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_string(parcel, STRING_GET(h->value[i]));
+)__c_cb";
+
+/**
+ * <PARCEL_TYPE> The type of the parcel of the value.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_BASE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel, h->value[i]);
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user-defined type.
+ * <NAME> The name of the user-defined type.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_READ[] =
+R"__c_cb(
+ret = <PREFIX>_<NAME>_create(&value);
+if (ret != RPC_PORT_ERROR_NONE) {
+  _E("Failed to create handle. error(%d)", ret);
+  set_last_result(ret);
+  return;
+}
+
+rpc_port_parcel_read(parcel, &value->parcelable, value);
+if (get_last_result() != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data. error(%d)", get_last_result());
+  <PREFIX>_<NAME>_destroy(value);
+  return;
+}
+
+h->value[i] = value;
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_READ[] =
+R"__c_cb(
+value = nullptr;
+rpc_port_parcel_read_bundle(parcel, &value);
+if (value == nullptr) {
+  _E("Failed to read data");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
+}
+
+h->value[i] = value;
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_STRING_PARCEL_READ[] =
+R"__c_cb(
+value = nullptr;
+rpc_port_parcel_read_string(parcel, &value);
+if (value == nullptr) {
+  _E("Failed to read data");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
+}
+
+h->value[i] = value;
+)__c_cb";
+
+/**
+ * <PARCEL_TYPE> The type of the parcel of the value.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_BASE_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_<PARCEL_TYPE>(parcel, &value);
+h->value[i] = value;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the element type.
+ * <NAME> The name of the element type.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_USER_DEFINED_FREE[] =
+R"__c_cb(
+if (h->value) {
+  for (int i = 0; i < h->size; ++i) {
+    if (h->value[i])
+      <PREFIX>_<NAME>_destroy(h->value[i]);
+  }
+
+  free(h->value);
+}
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_BUNDLE_FREE[] =
+R"__c_cb(
+if (h->value) {
+  for (int i = 0; i < h->size; ++i) {
+    if (h->value[i])
+      bundle_free(h->value[i]);
+  }
+
+  free(h->value);
+}
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_STRING_FREE[] =
+R"__c_cb(
+if (h->value) {
+  for (int i = 0; i < h->size; ++i) {
+    if (h->value[i])
+      free(h->value[i]);
+  }
+
+  free(h->value);
+}
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_ARRAY_BASE_FREE[] =
+R"__c_cb(
+if (h->value)
+  free(h->value);
+)__c_cb";
+
+#endif  // IDLC_C_GEN_C_BODY_GEN_ARRAY_BASE_CB_H_
index 8d1273e..d270a5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 - 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.
  * limitations under the License.
  */
 
+#include <cstring>
 #include <vector>
 
+#include "idlc/gen/c_body_gen_array_base_cb.h"
 #include "idlc/gen/c_body_gen_base.h"
-
-namespace {
 #include "idlc/gen/c_body_gen_base_cb.h"
-}
+#include "idlc/gen/c_body_gen_list_base_cb.h"
 
 namespace tidl {
 
 CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr<Document> doc)
     : CGeneratorBase(doc) {
   parcel_type_map_ = {
+    {"none", ""},
     {"char", "byte"},
     {"int", "int32"},
     {"short", "int16"},
@@ -38,1242 +39,720 @@ CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr<Document> doc)
     {"bundle", "bundle"},
     {"file", "string"},
   };
-}
 
-void CBodyGeneratorBase::GenStructures(std::ofstream& stream) {
-  for (auto& i : GetDocument().GetBlocks()) {
-    if (i->GetType() == Block::TYPE_STRUCTURE) {
-      const Structure &st = static_cast<const Structure&>(*i);
-      GenStructure(stream, st);
-      for (auto& j : st.GetElements().GetElms()) {
-       auto& t = j->GetType();
-       AddStructureFromType(t);
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() == Block::TYPE_STRUCTURE) {
+      auto& st = static_cast<const Structure&>(*b);
+      for (auto& e : st.GetElements().GetElms()) {
+        auto& type = e->GetType();
+        AddStructureFromType(type);
       }
     } else {
-      const Interface &inf = static_cast<const Interface&>(*i);
+      auto& inf = static_cast<const Interface&>(*b);
       for (auto& d : inf.GetDeclarations().GetDecls()) {
         for (auto& p : d->GetParameters().GetParams()) {
-          if (IsDelegateType(inf, p->GetParameterType().GetBaseType()))
+          auto& type = p->GetParameterType().GetBaseType();
+          if (IsDelegateType(inf, type))
             continue;
-          AddStructureFromType(p->GetParameterType().GetBaseType());
+
+          AddStructureFromType(type, inf);
         }
       }
     }
   }
-
-  for (auto& p : GetStructures()) {
-    const Structure& st = *p.second;
-    GenStructure(stream, st);
-  }
 }
 
-void CBodyGeneratorBase::GenStructure(std::ofstream& stream,
-                                      const Structure& st) {
-  GenStructureDeclaration(stream, st);
-  GenStructureParcelSerializer(stream, st);
-  GenStructureParcelDeserializer(stream, st);
-  GenStructureConstructor(stream, st);
-  GenStructureDestructor(stream, st);
-  GenStructureCloner(stream, st);
-  GenStructureSetter(stream, st);
-  GenStructureGetter(stream, st);
-  GenStructureIterator(stream, st);
-  GenStructureRemover(stream, st);
-  GenStructureLengthGetter(stream, st);
+void CBodyGeneratorBase::GenIncludeHeader(std::ofstream& stream) {
+  std::string code;
+  code += "#include \"";
+  code += FileName.substr(0, FileName.length() - 2);
+  code += ".h\"";
+  stream << NLine(1);
+  stream << code;
+  stream << NLine(1);
 }
 
-void CBodyGeneratorBase::GenStructureDeclaration(std::ofstream& stream,
-                                                 const Structure& st) {
-  stream << SmartIndent(GenTemplateString(CB_STRUCT_DECL,
-        [&]()->std::string {
-          return st.GetComments();
-        },
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : st.GetElements().GetElms()) {
-            str += NLine(1) + GetStringFromElementType(i->GetType()) +
-                i->GetID() + ";";
-            if (i->GetType().ToString() == "array")
-              str += NLine(1) + "int " + i->GetID() + "_size;";
-          }
-          return str;
-        }));
+void CBodyGeneratorBase::GenLogTag(std::ofstream& stream,
+    const std::string& log_tag) {
+  std::string code = ReplaceAll(CB_LOG_TAG, "<LOG_TAG>", log_tag);
+  stream << code;
 }
 
-void CBodyGeneratorBase::GenStructureParcelSerializer(std::ofstream& stream,
-                                              const Structure& st) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_STRUCT_SERIALIZER, "##", GetStructIdWithNamespace(st)),
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : st.GetElements().GetElms()) {
-            str += NLine(1);
-            str += GetParcelWriteString(i->GetID(), i->GetType());
-          }
-          return str;
-        }));
+void CBodyGeneratorBase::GenLogDefinition(std::ofstream& stream) {
+  stream << SmartIndent(CB_LOG_DEF);
 }
 
-void CBodyGeneratorBase::GenStructureParcelDeserializer(std::ofstream& stream,
-                                                const Structure& st) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_STRUCT_DESERIALIZER, "##", GetStructIdWithNamespace(st)),
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : st.GetElements().GetElms()) {
-            str += NLine(1);
-            str += GetParcelReadString(i->GetID(), i->GetType());
-          }
-          return str;
-        }));
+void CBodyGeneratorBase::GenBaseDefinition(std::ofstream& stream) {
+  stream << SmartIndent(CB_BASE_DEF);
 }
 
-void CBodyGeneratorBase::GenStructureConstructor(std::ofstream& stream,
-                                                 const Structure& st) {
-  stream << SmartIndent(ReplaceAll(CB_STRUCT_CTOR, "##",
-      GetStructIdWithNamespace(st)));
-}
+void CBodyGeneratorBase::GenStructureDefs(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() == Block::TYPE_STRUCTURE) {
+      auto& st = static_cast<const Structure&>(*b);
+      GenStructureDef(stream, st);
+    }
+  }
 
-void CBodyGeneratorBase::GenStructureDestructor(std::ofstream& stream,
-                                                const Structure& st) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_STRUCT_DTOR, "##",
-            GetStructIdWithNamespace(st)),
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : st.GetElements().GetElms()) {
-            str += GetFinalizeString(i->GetID(), i->GetType(), "h->");
-          }
-          return str;
-        }));
+  for (auto& i : GetStructures()) {
+    auto& st = i.second;
+    GenStructureDef(stream, *st);
+  }
 }
 
-void CBodyGeneratorBase::GenStructureSetter(std::ofstream& stream,
-                                            const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    stream << SmartIndent(GenTemplateString(CB_STRUCT_SETTER,
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "list")
-              return "add";
-            return "set";
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            if (i->GetType().IsUserDefinedType())
-              return GetParcelParamTypeString(i->GetType());
-
-            if (i->GetType().ToString() == "list") {
-              if (i->GetType().GetMetaType()->IsUserDefinedType() ||
-                  i->GetType().GetMetaType()->ToString() == "list" ||
-                  i->GetType().GetMetaType()->ToString() == "array") {
-                return GetParcelParamTypeString(*i->GetType().GetMetaType());
-              } else {
-                return ConvertTypeToString(ParameterType::Direction::IN,
-                    *i->GetType().GetMetaType());
-              }
-            }
-
-            if (i->GetType().ToString() == "array") {
-              return GetStringFromElementType(i->GetType());
-            }
-
-            return ConvertTypeToString(ParameterType::Direction::IN,
-                i->GetType());
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "array") {
-              std::string str;
-              str += i->GetID();
-              str += ", ";
-              str += "int " + i->GetID() + "_size";
-              return str;
-            }
-            return i->GetID();
-          },
-          [&]()->std::string {
-            if ((i->GetType().IsUserDefinedType() ||
-                 i->GetType().ToString() == "string" ||
-                 i->GetType().ToString() == "bundle" ||
-                 i->GetType().ToString() == "file") ||
-                ((i->GetType().ToString() == "list" ||
-                  i->GetType().ToString() == "array") &&
-                  (i->GetType().GetMetaType()->IsUserDefinedType() ||
-                   i->GetType().GetMetaType()->ToString() == "list" ||
-                   i->GetType().GetMetaType()->ToString() == "array" ||
-                   i->GetType().GetMetaType()->ToString() == "string" ||
-                   i->GetType().GetMetaType()->ToString() == "bundle" ||
-                   i->GetType().GetMetaType()->ToString() == "file")))
-              return "!h || !" + i->GetID();
-
-            return "!h";
-          },
-          [&]()->std::string {
-            std::string str;
-            str += NLine(1);
-            str += GetSetterString(i->GetID(), i->GetType());
-            return str;
-          }));
-  }
+void CBodyGeneratorBase::GenStructureDef(std::ofstream& stream,
+    const Structure& st) {
+  if (st.GetID().compare(0, strlen("array"), "array") == 0)
+    GenStructureArrayDef(stream, st);
+  else if (st.GetID().compare(0, strlen("list"), "list") == 0)
+    GenStructureListDef(stream, st);
+  else
+    GenStructureBaseDef(stream, st);
 }
 
-void CBodyGeneratorBase::GenStructureGetter(std::ofstream& stream,
-                                            const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() == "list")
-      continue;
+// @see #CB_STRUCTURE_ARRAY_DEF
+void CBodyGeneratorBase::GenStructureArrayDef(std::ofstream& stream,
+    const Structure& st) {
+  std::string code = ReplaceAll(CB_STRUCTURE_ARRAY_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", st.GetID());
 
-    stream << SmartIndent(GenTemplateString(CB_STRUCT_GETTER,
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "array")
-              return GetStringFromElementType(i->GetType()) + "*";
-
-            return ConvertTypeToString(ParameterType::Direction::OUT,
-                i->GetType());
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "array") {
-              std::string str;
-              str += i->GetID();
-              str += ", ";
-              str += "int *" + i->GetID() + "_size";
-              return str;
-            }
-            return i->GetID();
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "array") {
-              std::string str;
-              str += "!";
-              str += i->GetID();
-              str += " || ";
-              str += "!" + i->GetID() + "_size";
-              return str;
-            }
-            return "!" + i->GetID();
-          },
-          [&]()->std::string {
-            std::string str;
-            str += NLine(1);
-            str += GetGetterString(i->GetID(), i->GetType());
-            return str;
-          }));
-  }
+  auto& elm = st.GetElements().GetElms().front();
+  auto& type = elm->GetType();
+  auto element_type = GetDataTypeString(type, false);
+  code = ReplaceAll(code, "<ELEMENT_TYPE>", element_type);
+
+  stream << SmartIndent(code);
 }
 
-void CBodyGeneratorBase::GenStructureIterator(std::ofstream& stream,
-                                              const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() != "list")
-      continue;
+// @see #CB_STRUCTURE_LIST_DEF
+void CBodyGeneratorBase::GenStructureListDef(std::ofstream& stream,
+    const Structure& st) {
+  std::string code = ReplaceAll(CB_STRUCTURE_LIST_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", st.GetID());
 
-    stream << SmartIndent(GenTemplateString(CB_STRUCT_ITERATOR,
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            if (i->GetType().GetMetaType()->IsUserDefinedType() ||
-                i->GetType().GetMetaType()->ToString() == "list" ||
-                i->GetType().GetMetaType()->ToString() == "array")
-              return GetParcelParamTypeString(*i->GetType().GetMetaType());
-
-            return ConvertTypeToString(ParameterType::Direction::IN,
-                *i->GetType().GetMetaType());
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            std::string str;
-            str += NLine(1);
-            str += GetIteratorString(i->GetID(), i->GetType());
-            return str;
-          }));
-  }
+  stream << SmartIndent(code);
 }
 
-void CBodyGeneratorBase::GenStructureRemover(std::ofstream& stream,
-                                             const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() != "list")
-      continue;
+// @see #CB_STRUCTURE_BASE_DEF
+void CBodyGeneratorBase::GenStructureBaseDef(std::ofstream& stream,
+    const Structure& st) {
+  std::string code = ReplaceAll(CB_STRUCTURE_BASE_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", st.GetID());
 
-    stream << SmartIndent(GenTemplateString(CB_STRUCT_REMOVER,
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            if (i->GetType().GetMetaType()->IsUserDefinedType() ||
-                i->GetType().GetMetaType()->ToString() == "list" ||
-                i->GetType().GetMetaType()->ToString() == "array" ||
-                i->GetType().GetMetaType()->ToString() == "string" ||
-                i->GetType().GetMetaType()->ToString() == "bundle" ||
-                i->GetType().GetMetaType()->ToString() == "file")
-              return GetParcelParamTypeString(*i->GetType().GetMetaType());
-
-            return ConvertTypeToString(ParameterType::Direction::IN,
-                *i->GetType().GetMetaType(), false);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            std::string str;
-
-            if (i->GetType().GetMetaType()->IsUserDefinedType() ||
-                i->GetType().GetMetaType()->ToString() == "list" ||
-                i->GetType().GetMetaType()->ToString() == "array") {
-              str = GetHandlePrefix()
-                  + GetFullNameFromType(*i->GetType().GetMetaType())
-                  + "_destroy(value);";
-            } else {
-              str = GetFinalizeString("value", *i->GetType().GetMetaType(), "");
-            }
-
-            if (str == "")
-              return "free(value);\n";
-            return str;
-          }));
-  }
+  auto& elms = st.GetElements();
+  code = ReplaceAll(code, "<ELEMENTS>", GenBaseElements(elms));
+
+  stream << SmartIndent(code);
 }
 
-void CBodyGeneratorBase::GenStructureLengthGetter(std::ofstream& stream,
-                                                  const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() != "list")
-      continue;
+void CBodyGeneratorBase::GenStructures(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() == Block::TYPE_STRUCTURE) {
+      auto& st = static_cast<const Structure&>(*b);
+      GenStructure(stream, st);
+    }
+  }
 
-    stream << SmartIndent(GenTemplateString(CB_STRUCT_LENGTH_GETTER,
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          }));
+  for (auto& i : GetStructures()) {
+    auto& st = i.second;
+    GenStructure(stream, *st);
   }
 }
 
-void CBodyGeneratorBase::GenStructureCloner(std::ofstream& stream,
-                                            const Structure& st) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_STRUCT_CLONER, "##", GetStructIdWithNamespace(st)),
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : st.GetElements().GetElms()) {
-            str += NLine(1);
-            str += GetClonerString(i->GetID(), i->GetType(), st);
-          }
-          return str;
-        }));
-}
+void CBodyGeneratorBase::GenStructure(std::ofstream& stream,
+    const Structure& st) {
+  if (st.GetID().compare(0, strlen("array"), "array") == 0)
+    GenStructureArrayBase(stream, st);
+  else if (st.GetID().compare(0, strlen("list"), "list") == 0)
+    GenStructureListBase(stream, st);
+  else
+    GenStructureBase(stream, st);
+}
+
+// @see #CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_WRITE
+// @see #CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_WRITE
+// @see #CB_STRUCTURE_ARRAY_STRING_PARCEL_WRITE
+// @see #CB_STRUCTURE_ARRAY_BASE_PARCEL_WRITE
+std::string CBodyGeneratorBase::GenArrayParcelWrite(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = std::string(CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_WRITE);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_WRITE);
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = std::string(CB_STRUCTURE_ARRAY_STRING_PARCEL_WRITE);
+  } else {
+    code = ReplaceAll(CB_STRUCTURE_ARRAY_BASE_PARCEL_WRITE, "<PARCEL_TYPE>",
+        GetParcelType(type));
+  }
 
-std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type,
-                                                    bool meta_type) {
-  if (type.IsUserDefinedType())
-    return "";
+  return RemoveLine(code);
+}
 
-  if (type.ToString() == "list" ||
+// @see #CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_READ
+// @see #CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_READ
+// @see #CB_STRUCTURE_ARRAY_STRING_PARCEL_READ
+// @see #CB_STRUCTURE_ARRAY_BASE_PARCEL_READ
+std::string CBodyGeneratorBase::GenArrayParcelRead(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
       type.ToString() == "array") {
-    if (meta_type)
-      return "";
-    return "array_count";
+    code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_READ, "<PREFIX>",
+        GetHandlePrefix());
+
+    std::string name;
+    auto* meta_type = type.GetMetaType();
+    if (meta_type == nullptr)
+      name = type.ToString();
+    else
+      name = GetFullNameFromType(*meta_type);
+
+    code = ReplaceAll(code, "<NAME>", name);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_READ);
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = std::string(CB_STRUCTURE_ARRAY_STRING_PARCEL_READ);
+  } else {
+    code = ReplaceAll(CB_STRUCTURE_ARRAY_BASE_PARCEL_READ, "<PARCEL_TYPE>",
+        GetParcelType(type));
   }
 
-  return parcel_type_map_[type.ToString()];
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetParcelWriteFunctionString(
-    const BaseType& type, bool meta_type) {
-  std::string str = "rpc_port_parcel_write";
-  std::string parcel_type = GetParcelTypeString(type, meta_type);
-  if (parcel_type != "")
-    str += "_" + parcel_type;
+// @see #CB_STRUCTURE_ARRAY_USER_DEFINED_FREE
+// @see #CB_STRUCTURE_ARRAY_BUNDLE_FREE
+// @see #CB_STRUCTURE_ARRAY_STRING_FREE
+// @see #CB_STRUCTURE_ARRAY_BASE_FREE
+std::string CBodyGeneratorBase::GenArrayElementsFree(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_FREE, "<PREFIX>",
+        GetHandlePrefix());
 
-  return str;
-}
+    std::string name;
+    auto* meta_type = type.GetMetaType();
+    if (meta_type == nullptr)
+      name = type.ToString();
+    else
+      name = GetFullNameFromType(*meta_type);
 
-std::string CBodyGeneratorBase::GetParcelWriteString(const std::string& id,
-                                                     const BaseType& type) {
-  std::string str;
-  const char parcel[] = "$$(parcel, $$);";
-  const char ternary_operation[] = "## ? ## : \"\"";
-
-  str += GenTemplateString(parcel,
-      [&]()->std::string {
-        return GetParcelWriteFunctionString(type);
-      },
-      [&]()->std::string {
-        if (type.IsUserDefinedType())
-          return "&h->" + id + "->parcelable, h->" + id;
-        if (type.ToString() == "list")
-          return "g_list_length(h->" + id + ")";
-        if (type.ToString() == "array")
-          return "h->" + id + "_size";
-        if (type.ToString() == "string")
-          return ReplaceAll(ternary_operation, "##", "h->" + id);
-        return "h->" + id;
-      });
-
-  if (type.ToString() == "list") {
-    str += GenTemplateString(CB_WRITE_LIST_BLOCK,
-        [&]()->std::string {
-          return "h->" + id;
-        },
-        [&]()->std::string {
-          return GetParcelParamTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          return GenTemplateString(parcel,
-              [&]()->std::string {
-                return GetParcelWriteFunctionString(*type.GetMetaType(), true);
-              },
-              [&]()->std::string {
-                if (type.GetMetaType()->IsUserDefinedType() ||
-                    type.GetMetaType()->ToString() == "list" ||
-                    type.GetMetaType()->ToString() == "array")
-                  return "&value->parcelable, value";
-                if (type.GetMetaType()->ToString() == "bundle")
-                  return "value";
-                if (type.GetMetaType()->ToString() == "string"
-                    || type.GetMetaType()->ToString() == "file")
-                  return ReplaceAll(ternary_operation, "##", "value");
-                return "*value";
-              });
-        });
-  } else if (type.ToString() == "array") {
-    str += GenTemplateString(CB_WRITE_ARRAY_BLOCK,
-        [&]()->std::string {
-          return "h->" + id + "_size";
-        },
-        [&]()->std::string {
-          return GenTemplateString(parcel,
-              [&]()->std::string {
-                return GetParcelWriteFunctionString(*type.GetMetaType(), true);
-              },
-              [&]()->std::string {
-                if (type.GetMetaType()->IsUserDefinedType() ||
-                    type.GetMetaType()->ToString() == "list" ||
-                    type.GetMetaType()->ToString() == "array")
-                  return "&h->" + id + "[i]->parcelable, h->" + id +"[i]";
-                if (type.GetMetaType()->ToString() == "string" ||
-                    type.GetMetaType()->ToString() == "file")
-                  return ReplaceAll(ternary_operation, "##", "h->" + id
-                      + "[i]");
-                return "h->" + id + "[i]";
-              });
-        });
+    code = ReplaceAll(code, "<NAME>", name);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_ARRAY_BUNDLE_FREE);
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = std::string(CB_STRUCTURE_ARRAY_STRING_FREE);
+  } else {
+    code = std::string(CB_STRUCTURE_ARRAY_BASE_FREE);
   }
 
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetParcelReadFunctionString(
-    const BaseType& type, bool meta_type) {
-  std::string str = "rpc_port_parcel_read";
-  std::string parcel_type = GetParcelTypeString(type, meta_type);
-  if (parcel_type != "")
-    str += "_" + parcel_type;
+// @see #CB_STRUCTURE_ARRAY_BASE
+void CBodyGeneratorBase::GenStructureArrayBase(std::ofstream& stream,
+    const Structure& st) {
+  std::string code = ReplaceAll(CB_STRUCTURE_ARRAY_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", st.GetID());
 
-  return str;
+  auto& elm = st.GetElements().GetElms().front();
+  code = ReplaceAll(code, "<PARCEL_WRITE>", GenArrayParcelWrite(elm));
+  code = ReplaceAll(code, "<PARCEL_READ>", GenArrayParcelRead(elm));
+
+  auto& type = elm->GetType();
+  auto param_type = GetParamTypeString(ParameterType::Direction::IN, type);
+  code = ReplaceAll(code, "<PARAM_TYPE_IN>", param_type);
+  param_type = GetParamTypeString(ParameterType::Direction::OUT, type);
+  code = ReplaceAll(code, "<PARAM_TYPE_OUT>", param_type);
+
+  auto element_type = GetDataTypeString(type, false);
+  code = ReplaceAll(code, "<ELEMENT_TYPE>", element_type);
+  auto element_type_size = GetDataTypeString(type, false);
+  element_type_size = RemoveLastSpaces(element_type_size);
+  code = ReplaceAll(code, "<ELEMENT_TYPE_SIZE>", element_type_size);
+  code = ReplaceAll(code, "<ELEMENTS_FREE>", GenArrayElementsFree(elm));
+
+  stream << SmartIndent(code);
 }
 
-std::string CBodyGeneratorBase::GetParcelReadString(const std::string& id,
-                                                    const BaseType& type) {
-  std::string str;
-  const char parcel[] = "$$(parcel, $$);";
-
-  if (type.ToString() == "list") {
-    str += GenTemplateString(CB_READ_LIST_BLOCK,
-        [&]()->std::string {
-          return GenTemplateString(parcel,
-              [&]()->std::string {
-                return GetParcelReadFunctionString(type);
-              },
-              [&]()->std::string {
-                return "&len";
-              });
-        },
-        [&]()->std::string {
-          return GetParcelParamTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          std::string s;
-
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array") {
-            s += GetConstructorString(*type.GetMetaType(), "value");
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!value";
-                },
-                [&]()->std::string {
-                  std::string ss;
-                  ss += "_E(\"Failed to create handle\");" + NLine(1);
-                  ss += "return;";
-                  return ss;
-                });
-            s += NLine(1);
-            s += GenTemplateString(parcel,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(*type.GetMetaType(), true);
-                },
-                [&]()->std::string {
-                  return "&value->parcelable, value";
-                });
-          } else if (type.GetMetaType()->ToString() == "string" ||
-                     type.GetMetaType()->ToString() == "bundle"||
-                     type.GetMetaType()->ToString() == "file") {
-            s += GenTemplateString(parcel,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(*type.GetMetaType());
-                },
-                [&]()->std::string {
-                  return "&value";
-                });
-          } else {
-            s += "value = calloc(1, sizeof(*value));" + NLine(1);
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!value";
-                },
-                [&]()->std::string {
-                  std::string ss;
-                  ss += "_E(\"Out of memory\");" + NLine(1);
-                  ss += "return;";
-                  return ss;
-                });
-            s += NLine(1);
-            s += GenTemplateString(parcel,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(*type.GetMetaType());
-                },
-                [&]()->std::string {
-                  return "value";
-                });
-          }
-
-          return s;
-        },
-        [&]()->std::string {
-          return "h->" + id;
-        },
-        [&]()->std::string {
-          return "h->" + id;
-        });
-  } else if (type.ToString() == "array") {
-    str += GenTemplateString(ReplaceAll(CB_READ_ARRAY_BLOCK, "##", id),
-        [&]()->std::string {
-          return GenTemplateString(parcel,
-              [&]()->std::string {
-                return GetParcelReadFunctionString(type);
-              },
-              [&]()->std::string {
-                return "&h->" + id + "_size";
-              });
-        },
-        [&]()->std::string {
-          return GetReturnTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          return GetErrorValue(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          std::string s;
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array") {
-            s += GetConstructorString(*type.GetMetaType(), "value");
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!value";
-                },
-                [&]()->std::string {
-                  std::string ss;
-                  ss += "_E(\"Failed to create handle\");" + NLine(1);
-                  ss += "return;";
-                  return ss;
-                });
-            s += NLine(1);
-            s += GenTemplateString(parcel,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(*type.GetMetaType(), true);
-                },
-                [&]()->std::string {
-                  return "&value->parcelable, value";
-                });
-          } else {
-            s += GenTemplateString(parcel,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(*type.GetMetaType());
-                },
-                [&]()->std::string {
-                  return "&value";
-                });
-          }
-          s += NLine(1);
-          s += GetSetterString("h->" + id + "[i]", "value");
-          return s;
-        });
-  } else if (type.IsUserDefinedType()) {
-    str += GenTemplateString(ReplaceAll(CB_READ_USER_DEFINED_BLOCK, "##", id),
-        [&]()->std::string {
-          return GetFullNameFromType(type);
-        });
+// @see #CB_STRUCTURE_LIST_USER_DEFINED_FREE
+// @see #CB_STRUCTURE_LIST_BUNDLE_FREE
+// @see #CB_STRUCTURE_LIST_STRING_FREE
+// @see #CB_STRUCTURE_LIST_BASE_FREE
+std::string CBodyGeneratorBase::GenListDataFree(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_FREE, "<PREFIX>",
+        GetHandlePrefix());
+
+    std::string name;
+    auto* meta_type = type.GetMetaType();
+    if (meta_type == nullptr)
+      name = type.ToString();
+    else
+      name = GetFullNameFromType(*meta_type);
+
+    code = ReplaceAll(code, "<NAME>", name);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_LIST_BUNDLE_FREE);
+  } else if (type.ToString() == "string" || type.ToString() == "flie") {
+    code = std::string(CB_STRUCTURE_LIST_STRING_FREE);
   } else {
-    str += GenTemplateString(parcel,
-        [&]()->std::string {
-          return GetParcelReadFunctionString(type);
-        },
-        [&]()->std::string {
-          if (type.IsUserDefinedType())
-            return "&h->" + id + "->parcelable, h->" + id;
-          return "&h->" + id;
-        });
+    code = std::string(CB_STRUCTURE_LIST_BASE_FREE);
   }
 
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetFinalizeString(const std::string& id,
-    const BaseType& type, const std::string& handle) {
-  std::string str;
-
-  if (!type.IsUserDefinedType() &&
-       type.ToString() != "list" &&
-       type.ToString() != "array" &&
-       type.ToString() != "string" &&
-       type.ToString() != "bundle" &&
-       type.ToString() != "file")
-    return str;
-
-  if (type.ToString() == "list") {
-    str += GenTemplateString(CB_FINALIZE_LIST_BLOCK,
-        [&]()->std::string {
-          return handle + id;
-        },
-        [&]()->std::string {
-          return GetParcelParamTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          return GenTemplateString(CB_IF_STATEMENT,
-              [&]()->std::string {
-                return "value";
-              },
-              [&]()->std::string {
-                return GetDestructorString(*type.GetMetaType(),
-                    "value", true) + NLine(1);
-              });
-        },
-        [&]()->std::string {
-          return handle + id;
-        });
-  } else if (type.ToString() == "array") {
-    if (!type.GetMetaType()->IsUserDefinedType() &&
-         type.GetMetaType()->ToString() != "list" &&
-         type.GetMetaType()->ToString() != "array" &&
-         type.GetMetaType()->ToString() != "string" &&
-         type.GetMetaType()->ToString() != "bundle" &&
-         type.GetMetaType()->ToString() != "file") {
-      return GenTemplateString(CB_IF_STATEMENT,
-              [&]()->std::string {
-                return handle + id;
-              },
-              [&]()->std::string {
-                return "free(" + handle + id + ");";
-              });
-    }
-    str += GenTemplateString(CB_FINALIZE_ARRAY_BLOCK,
-        [&]()->std::string {
-          return handle + id + "_size";
-        },
-        [&]()->std::string {
-          return GenTemplateString(CB_IF_STATEMENT,
-              [&]()->std::string {
-                return handle + id + "[j]";
-              },
-              [&]()->std::string {
-                return GetDestructorString(*type.GetMetaType(),
-                    handle + id + "[j]", true) + NLine(1);
-              });
-        },
-        [&]()->std::string {
-          return handle + id;
-        });
+// @see #CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_WRITE
+// @see #CB_STRUCTURE_LIST_BUNDLE_PARCEL_WRITE
+// @see #CB_STRUCTURE_LIST_STRING_PARCEL_WRITE
+// @see #CB_STRUCTURE_LIST_BASE_PARCEL_WRITE
+std::string CBodyGeneratorBase::GenListParcelWrite(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = std::string(CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_WRITE);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_LIST_BUNDLE_PARCEL_WRITE);
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = std::string(CB_STRUCTURE_LIST_STRING_PARCEL_WRITE);
   } else {
-    str += GenTemplateString(CB_IF_STATEMENT,
-        [&]()->std::string {
-          return handle + id;
-        },
-        [&]()->std::string {
-          return GetDestructorString(type, handle + id) + NLine(1);
-        });
+    code = ReplaceAll(CB_STRUCTURE_LIST_BASE_PARCEL_WRITE, "<PARCEL_TYPE>",
+        GetParcelType(type));
   }
 
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetSetterString(const std::string& id,
-                                                const BaseType& type) {
-  std::string str;
-
+// @see #CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_READ
+// @see #CB_STRUCTURE_LIST_BUNDLE_PARCEL_READ
+// @see #CB_STRUCTURE_LIST_STRING_PARCEL_READ
+// @see #CB_STRUCTURE_LIST_BASE_PARCEL_READ
+std::string CBodyGeneratorBase::GenListParcelRead(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
   if (type.IsUserDefinedType() ||
-      type.ToString() == "string" ||
-      type.ToString() == "bundle" ||
-      type.ToString() == "file") {
-    str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-        [&]()->std::string {
-          return "h->" + id;
-        },
-        [&]()->std::string {
-          std::string s;
-          s += GetDestructorString(type, "h->" + id) + NLine(1);
-          s += GetSetterString("h->" + id, "NULL");
-          return s;
-        });
-    str += NLine(1);
-
-    str += NLine(1);
-    str += GetSetterString(type, "h->" + id, id);
-    str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-        [&]()->std::string {
-          return "!h->" + id;
-        },
-        [&]()->std::string {
-          std::string s;
-          s += "_E(\"Failed to duplicate data\");" + NLine(1);
-          s += "return -1;";
-          return s;
-        });
-    str += NLine(1);
-  } else if (type.ToString() == "list") {
-    str += GenTemplateString(CB_SETTER_LIST_BLOCK,
-        [&]()->std::string {
-          return GetParcelParamTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          std::string s;
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "string" ||
-              type.GetMetaType()->ToString() == "bundle" ||
-              type.GetMetaType()->ToString() == "file" ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array") {
-            s += GetSetterString(*type.GetMetaType(), "value", id);
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!value";
-                },
-                [&]()->std::string {
-                  std::string s;
-                  s += "_E(\"Out of memory\");" + NLine(1);
-                  s += "return -1;";
-                  return s;
-                });
-            s += NLine(1);
-          } else {
-            s += "value = calloc(1, sizeof(*value));" + NLine(1);
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!value";
-                },
-                [&]()->std::string {
-                  std::string s;
-                  s += "_E(\"Out of memory\");" + NLine(1);
-                  s += "return -1;";
-                  return s;
-                });
-            s += NLine(1);
-            s += GetSetterString("*value", id);
-          }
-          return s;
-        },
-        [&]()->std::string {
-          return "h->" + id;
-        },
-        [&]()->std::string {
-          return "h->" + id;
-        });
-  } else if (type.ToString() == "array") {
-    str += GetFinalizeString(id, type, "h->") + NLine(1);
-    str += GetSetterString("h->" + id, "NULL");
-    str += NLine(1);
-    str += GenTemplateString(ReplaceAll(CB_SETTER_ARRAY_BLOCK, "##", id),
-        [&]()->std::string {
-          std::string s;
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array")
-            s += "int __ret = ";
-
-          s += GetSetterString(*type.GetMetaType(), "h->" + id + "[i]",
-              id + "[i]");
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array") {
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "__ret != 0";
-                },
-                [&]()->std::string {
-                  std::string r;
-                  r += "_E(\"Failed to clone " + id + "\");" + NLine(1);
-                  r += GetFinalizeString(id, type, "h->") + NLine(1);
-                  r += GetSetterString("h->" + id, "NULL") + NLine(1);
-                  r += "return -1;";
-                  return r;
-                });
-          }
-
-          s += NLine(1);
-          return s;
-        });
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_READ, "<PREFIX>",
+        GetHandlePrefix());
+
+    std::string name;
+    auto* meta_type = type.GetMetaType();
+    if (meta_type == nullptr)
+      name = type.ToString();
+    else
+      name = GetFullNameFromType(*meta_type);
+
+    code = ReplaceAll(code, "<NAME>", name);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_LIST_BUNDLE_PARCEL_READ);
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = std::string(CB_STRUCTURE_LIST_STRING_PARCEL_READ);
   } else {
-    str += GetSetterString(type, "h->" + id, id);
+    auto value_type = GetParamTypeString(ParameterType::Direction::IN, type);
+    value_type = RemoveLastSpaces(value_type);
+    code = ReplaceAll(CB_STRUCTURE_LIST_BASE_PARCEL_READ, "<VALUE_TYPE>",
+        value_type);
+    code = ReplaceAll(code, "<PARCEL_TYPE>", GetParcelType(type));
   }
 
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetGetterString(const std::string& id,
-                                                const BaseType& type) {
-  std::string str;
-
-  if (type.ToString() == "array") {
-    str += GenTemplateString(ReplaceAll(CB_GETTER_ARRAY_BLOCK, "##", id),
-        [&]()->std::string {
-          std::string s;
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array")
-            s += "int __ret = ";
-
-          s += GetSetterString(*type.GetMetaType(),
-              "(*" + id + ")[i]", "h->" + id + "[i]");
-
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array") {
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "__ret != 0";
-                },
-                [&]()->std::string {
-                  std::string r;
-                  r += "_E(\"Failed to clone " + id + "\");" + NLine(1);
-                  r += GetFinalizeString("*" + id, type, "") + NLine(1);
-                  r += GetSetterString("*" + id, "NULL") + NLine(1);
-                  r += "return -1;";
-                  return r;
-                });
-          }
-
-          s += NLine(1);
-          return s;
-        });
-  } else {
-    if (type.IsUserDefinedType() ||
-        type.ToString() == "string" ||
-        type.ToString() == "bundle" ||
-        type.ToString() == "file") {
-      str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-          [&]()->std::string {
-            return "!h->" + id;
-          },
-          [&]()->std::string {
-            std::string s;
-            s += "_E(\"Invalid parameter: h->" + id + " is NULL\");" + NLine(1);
-            s += "return -1;";
-            return s;
-          });
-      str += NLine(1);
-      str += NLine(1);
-    }
+// @see #CB_STRUCTURE_LIST_USER_DEFINED_ADD
+// @see #CB_STRUCTURE_LIST_BUNDLE_ADD
+// @see #CB_STRUCTURE_LIST_STRING_ADD
+// @see #CB_STRUCTURE_LIST_BASE_ADD
+std::string CBodyGeneratorBase::GenListAdd(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_ADD, "<PREFIX>",
+        GetHandlePrefix());
 
-    if (type.IsUserDefinedType()) {
-      str += GetHandlePrefix() + GetFullNameFromType(type) +
-        "_clone(h->"+ id + ", " + id +");" + NLine(1);
-    } else {
-      str += GetSetterString(type, "*" + id, "h->" + id);
-    }
+    std::string name;
+    auto* meta_type = type.GetMetaType();
+    if (meta_type == nullptr)
+      name = type.ToString();
+    else
+      name = GetFullNameFromType(*meta_type);
 
-    if (type.IsUserDefinedType() ||
-        type.ToString() == "string" ||
-        type.ToString() == "bundle" ||
-        type.ToString() == "file") {
-      str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-          [&]()->std::string {
-            return "*" + id + " == NULL";
-          },
-          [&]()->std::string {
-            std::string s;
-            s += "_E(\"Failed to duplicate " + id + "\");" + NLine(1);
-            s += "return -1;";
-            return s;
-          });
-      str += NLine(1);
-    }
+    code = ReplaceAll(code, "<NAME>", name);
+  } else if (type.ToString() == "bundle") {
+    code = std::string(CB_STRUCTURE_LIST_BUNDLE_ADD);
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = std::string(CB_STRUCTURE_LIST_STRING_ADD);
+  } else {
+    auto value_type = GetParamTypeString(ParameterType::Direction::IN, type);
+    code = ReplaceAll(CB_STRUCTURE_LIST_BASE_ADD, "<VALUE_TYPE>",
+        value_type);
   }
-  return str;
-}
 
-std::string CBodyGeneratorBase::GetIteratorString(const std::string& id,
-                                                  const BaseType& type) {
-  std::string str;
-
-  str += GenTemplateString(CB_ITERATOR_BLOCK,
-      [&]()->std::string {
-        return "h->" + id;
-      },
-      [&]()->std::string {
-        return GetParcelParamTypeString(*type.GetMetaType());
-      },
-      [&]()->std::string {
-        if (type.GetMetaType()->IsUserDefinedType() ||
-            type.GetMetaType()->ToString() == "list" ||
-            type.GetMetaType()->ToString() == "array" ||
-            type.GetMetaType()->ToString() == "string" ||
-            type.GetMetaType()->ToString() == "bundle" ||
-            type.GetMetaType()->ToString() == "file")
-          return "value";
-
-        return "*value";
-      });
-
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetClonerString(const std::string& id,
-                                                const BaseType& type,
-                                                const Structure& st) {
-  std::string str;
-
+std::string CBodyGeneratorBase::GenListCallbackParamType(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
   if (type.IsUserDefinedType() ||
-      type.ToString() == "string" ||
+      type.ToString() == "list" ||
+      type.ToString() == "array"||
       type.ToString() == "bundle" ||
-      type.ToString() == "file") {
-    str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-        [&]()->std::string {
-          return "h->" + id;
-        },
-        [&]()->std::string {
-          std::string s;
-          s += GetSetterString(type, "handle->" + id, "h->" + id);
-          s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-              [&]()->std::string {
-                return "!handle->" + id;
-              },
-              [&]()->std::string {
-                std::string ss;
-                ss += "_E(\"Failed to duplicate h->" + id + "\");" + NLine(1);
-                ss += "rpc_port_" + GetStructIdWithNamespace(st)
-                   + "_destroy(handle);" + NLine(1);
-                ss += "return -1;";
-                return ss;
-              });
-          return s;
-        });
-    str += NLine(1);
-  } else  if (type.ToString() == "list") {
-    str += GenTemplateString(CB_CLONER_LIST_BLOCK,
-        [&]()->std::string {
-          return "h->" + id;
-        },
-        [&]()->std::string {
-          return GetParcelParamTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          return GetParcelParamTypeString(*type.GetMetaType());
-        },
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          std::string s;
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array" ||
-              type.GetMetaType()->ToString() == "string" ||
-              type.GetMetaType()->ToString() == "bundle" ||
-              type.GetMetaType()->ToString() == "file") {
-            s += GetSetterString(*type.GetMetaType(),
-                "new_value", "value");
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!new_value";
-                },
-              [&]()->std::string {
-                std::string ss;
-                ss += "_E(\"Failed to duplicate value\");" + NLine(1);
-                ss += "rpc_port_" + GetStructIdWithNamespace(st)
-                   + "_destroy(handle);" + NLine(1);
-                ss += "return -1;";
-                return ss;
-              });
-          } else {
-            s += "new_value = calloc(1, sizeof(*new_value));" + NLine(1);
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "!new_value";
-                },
-                [&]()->std::string {
-                  std::string tmp;
-                  tmp += "_E(\"Out of memory\");" + NLine(1);
-                  tmp += "rpc_port_" + GetStructIdWithNamespace(st)
-                      + "_destroy(handle);" + NLine(1);
-                  tmp += "return -1;";
-                  return tmp;
-                });
-            s += NLine(1);
-            s += GetSetterString(*type.GetMetaType(),
-                "*new_value", "*value");
-          }
-          s += NLine(1);
-          return s;
-        },
-        [&]()->std::string {
-          return "handle->" + id;
-        },
-        [&]()->std::string {
-          return "handle->" + id;
-        });
-  } else if (type.ToString() == "array") {
-    str += GenTemplateString(ReplaceAll(CB_CLONER_ARRAY_BLOCK, "##", id),
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          std::string s;
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array")
-            s += "int __ret = ";
-
-          s += GetSetterString(*type.GetMetaType(),
-              "handle->" + id + "[i]", "h->" + id + "[i]");
-
-          if (type.GetMetaType()->IsUserDefinedType() ||
-              type.GetMetaType()->ToString() == "list" ||
-              type.GetMetaType()->ToString() == "array") {
-            s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES,
-                [&]()->std::string {
-                  return "__ret != 0";
-                },
-                [&]()->std::string {
-                  std::string tmp;
-                  tmp += "_E(\"Failed to clone " + id + "\");" + NLine(1);
-                  tmp += "rpc_port_" + GetStructIdWithNamespace(st) +
-                      "_destroy(handle);" + NLine(1);
-                  tmp += "return -1;";
-                  return tmp;
-                });
-          }
-
-          s += NLine(1);
-          return s;
-        });
-  } else {
-    str += GetSetterString(type, "handle->" + id, "h->" + id);
-  }
+      type.ToString() == "string" ||
+      type.ToString() == "file")
+    code = std::string("value");
+  else
+    code = std::string ("*value");
+
+  return code;
+}
+
+// @see #CB_STRUCTURE_LIST_BASE
+void CBodyGeneratorBase::GenStructureListBase(std::ofstream& stream,
+    const Structure& st) {
+  std::string code = ReplaceAll(CB_STRUCTURE_LIST_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", st.GetID());
+
+  auto& elm = st.GetElements().GetElms().front();
+  auto& type = elm->GetType();
+  code = ReplaceAll(code, "<DATA_TYPE>", GetDataTypeString(type, true));
+  code = ReplaceAll(code, "<DATA_FREE>", GenListDataFree(elm));
 
-  return str;
+  auto param_type = GetParamTypeString(ParameterType::Direction::IN, type);
+  code = ReplaceAll(code, "<PARAM_TYPE_IN>", param_type);
+
+  code = ReplaceAll(code, "<PARCEL_WRITE>", GenListParcelWrite(elm));
+  code = ReplaceAll(code, "<PARCEL_READ>", GenListParcelRead(elm));
+
+  code = ReplaceAll(code, "<LIST_ADD>", GenListAdd(elm));
+  code = ReplaceAll(code, "<CALLBACK_PARAM_TYPE>",
+      GenListCallbackParamType(elm));
+
+  stream << SmartIndent(code);
 }
 
-std::string CBodyGeneratorBase::GetDestructorString(const BaseType& type,
-                                                    const std::string& value,
-                                                    bool container_value) {
-  std::string str;
+std::string CBodyGeneratorBase::GenBaseElements(const Elements& elms) {
+  std::string code;
+  for (auto& elm : elms.GetElms()) {
+    auto& type = elm->GetType();
+    auto param_type = GetDataTypeString(type, false);
+    code += param_type + elm->GetID() + ";";
+    code += NLine(1);
+  }
+
+  return code;
+}
 
+// @see #CB_STRUCTURE_BASE_USER_DEFINED_FREE
+// @see #CB_STRUCTURE_BASE_BUNDLE_FREE
+// @see #CB_STRUCTURE_BASE_STRING_FREE
+std::string CBodyGeneratorBase::GenBaseElementFree(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
   if (type.IsUserDefinedType() ||
       type.ToString() == "list" ||
       type.ToString() == "array") {
-    str += GetHandlePrefix() + GetFullNameFromType(type) +
-        "_destroy(" + value + ");";
+    code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_FREE, "<PREFIX>",
+        GetHandlePrefix());
+
+    std::string name = GetFullNameFromType(type);
+    code = ReplaceAll(code, "<NAME>", name);
+    code = ReplaceAll(code, "<ELEMENT_NAME>", elm->GetID());
   } else if (type.ToString() == "bundle") {
-    str += "bundle_free(" + value + ");";
-  } else if (type.ToString() == "string" || type.ToString() == "file" || container_value) {
-    str += "free(" + value + ");";
+    code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_FREE, "<ELEMENT_NAME>",
+        elm->GetID());
+  } else if (type.ToString() == "string" || type.ToString() == "flie") {
+    code = ReplaceAll(CB_STRUCTURE_BASE_STRING_FREE, "<ELEMENT_NAME>",
+        elm->GetID());
   }
 
-  return str;
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenBaseElementsFree(const Elements& elms) {
+  std::string code;
+  for (auto& elm : elms.GetElms())
+    code += GenBaseElementFree(elm);
+
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetConstructorString(const BaseType& type,
-                                                     const std::string& value) {
-  std::string str;
-  str += GetHandlePrefix() + GetFullNameFromType(type) +
-      "_create(&" + value + ");" + NLine(1);
-  return str;
+// @see #CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_WRITE
+// @see #CB_STRUCTURE_BASE_BUNDLE_PARCEL_WRITE
+// @see #CB_STRUCTURE_BASE_STRING_PARCEL_WRITE
+// @see #CB_STRUCTURE_BASE_BASE_PARCEL_WRITE
+std::string CBodyGeneratorBase::GenBaseParcelWrite(const Elements& elms) {
+  std::string code;
+  for (auto& elm : elms.GetElms()) {
+    std::string parcel_write_code;
+    auto& type = elm->GetType();
+    if (type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_write_code = ReplaceAll(
+          CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_WRITE, "<ELEMENT_NAME>",
+          elm->GetID());
+    } else if (type.ToString() == "bundle") {
+      parcel_write_code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_PARCEL_WRITE,
+          "<ELEMENT_NAME>", elm->GetID());
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      parcel_write_code = ReplaceAll(CB_STRUCTURE_BASE_STRING_PARCEL_WRITE,
+          "<ELEMENT_NAME>", elm->GetID());
+    } else {
+      parcel_write_code = ReplaceAll(CB_STRUCTURE_BASE_BASE_PARCEL_WRITE,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_write_code = ReplaceAll(parcel_write_code, "<ELEMENT_NAME>",
+          elm->GetID());
+    }
+
+    code += parcel_write_code;
+  }
+
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetSetterString(const BaseType& type,
-                                                const std::string& lvalue,
-                                                const std::string& rvalue) {
-  std::string str;
+// @see #CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_READ
+// @see #CB_STRUCTURE_BASE_BUNDLE_PARCEL_READ
+// @see #CB_STRUCTURE_BASE_STRING_PARCEL_READ
+// @see #CB_STRUCTURE_BASE_BASE_PARCEL_READ
+std::string CBodyGeneratorBase::GenBaseParcelRead(const Elements& elms) {
+  std::string code;
+  for (auto& elm : elms.GetElms()) {
+    std::string parcel_read_code;
+    auto& type = elm->GetType();
+    if (type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_read_code = ReplaceAll(
+          CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_READ, "<PREFIX>",
+          GetHandlePrefix());
+      parcel_read_code = ReplaceAll(parcel_read_code, "<NAME>",
+          GetFullNameFromType(type));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ELEMENT_NAME>",
+          elm->GetID());
+    } else if (type.ToString() == "bundle") {
+      parcel_read_code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_PARCEL_READ,
+          "<ELEMENT_NAME>", elm->GetID());
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      parcel_read_code = ReplaceAll(CB_STRUCTURE_BASE_STRING_PARCEL_READ,
+          "<ELEMENT_NAME>", elm->GetID());
+    } else {
+      parcel_read_code = ReplaceAll(CB_STRUCTURE_BASE_BASE_PARCEL_READ,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ELEMENT_NAME>",
+          elm->GetID());
+    }
+
+    code += parcel_read_code;
+  }
+
+  return RemoveLine(code);
+}
 
+// @see #CB_STRUCTURE_BASE_USER_DEFINED_SET
+// @see #CB_STRUCTURE_BASE_BUNDLE_SET
+// @see #CB_STRUCTURE_BASE_STRING_SET
+// @see #CB_STRUCTURE_BASE_BASE_SET
+std::string CBodyGeneratorBase::GenBaseSet(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
   if (type.IsUserDefinedType() ||
       type.ToString() == "list" ||
       type.ToString() == "array") {
-    str += GetHandlePrefix() + GetFullNameFromType(type) +
-        "_clone(" + rvalue + ", &" + lvalue +");" + NLine(1);
-  } else if (type.ToString() == "string" || type.ToString() == "file")  {
-    str += lvalue + " = strdup(" + rvalue + ");" + NLine(1);
+    code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_SET, "<PREFIX>",
+        GetHandlePrefix());
+    code = ReplaceAll(code, "<NAME>", GetFullNameFromType(type));
+
+    auto element_free_code = RemoveLine(GenBaseElementFree(elm));
+    code = ReplaceAll(code, "<ELEMENT_FREE>", element_free_code);
+    code = ReplaceAll(code, "<ELEMENT_NAME>", elm->GetID());
   } else if (type.ToString() == "bundle") {
-    str += lvalue + " = bundle_dup(" + rvalue + ");" + NLine(1);
+    auto element_free_code = RemoveLine(GenBaseElementFree(elm));
+    code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_SET, "<ELEMENT_FREE>",
+        element_free_code);
+    code = ReplaceAll(code, "<ELEMENT_NAME>", elm->GetID());
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    auto element_free_code = RemoveLine(GenBaseElementFree(elm));
+    code = ReplaceAll(CB_STRUCTURE_BASE_STRING_SET, "<ELEMENT_FREE>",
+        element_free_code);
+    code = ReplaceAll(code, "<ELEMENT_NAME>", elm->GetID());
   } else {
-    str += GetSetterString(lvalue, rvalue);
+    code = ReplaceAll(CB_STRUCTURE_BASE_BASE_SET, "<ELEMENT_NAME>",
+        elm->GetID());
   }
 
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CBodyGeneratorBase::GetSetterString(const std::string& lvalue,
-                                                const std::string& rvalue) {
-  std::string str;
-  str += lvalue + " = " + rvalue + ";";
-  return str;
+// @see #CB_STRUCTURE_BASE_USER_DEFINED_GET
+// @see #CB_STRUCTURE_BASE_BUNDLE_GET
+// @see #CB_STRUCTURE_BASE_STRING_GET
+// @see #CB_STRUCTURE_BASE_BASE_GET
+std::string CBodyGeneratorBase::GenBaseGet(
+    const std::unique_ptr<Element>& elm) {
+  std::string code;
+  auto& type = elm->GetType();
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_GET, "<PREFIX>",
+        GetHandlePrefix());
+    code = ReplaceAll(code, "<NAME>", GetFullNameFromType(type));
+    code = ReplaceAll(code, "<ELEMENT_NAME>", elm->GetID());
+  } else if (type.ToString() == "bundle") {
+    code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_GET, "<ELEMENT_NAME>",
+        elm->GetID());
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = ReplaceAll(CB_STRUCTURE_BASE_STRING_GET, "<ELEMENT_NAME>",
+        elm->GetID());
+  } else {
+    code = ReplaceAll(CB_STRUCTURE_BASE_BASE_GET, "<ELEMENT_NAME>",
+        elm->GetID());
+  }
+
+  return RemoveLine(code);
 }
 
-void CBodyGeneratorBase::GenIncludeHeader(std::ofstream& stream) {
-  std::string str;
-  str += "#include \"";
-  str += FileName.substr(0, FileName.length() - 2);
-  str += ".h\"";
-  stream << NLine(1);
-  stream << str;
-  stream << NLine(1);
+// @see #CB_STRUCTURE_BASE_SET_GET
+std::string CBodyGeneratorBase::GenBaseSetGet(const std::string& name,
+    const Elements& elms) {
+  std::string code;
+  for (auto& elm : elms.GetElms()) {
+    std::string set_get_code = ReplaceAll(CB_STRUCTURE_BASE_SET_GET,
+        "<PREFIX>", GetHandlePrefix());
+    set_get_code = ReplaceAll(set_get_code, "<NAME>", name);
+    set_get_code = ReplaceAll(set_get_code, "<ELEMENT_NAME>", elm->GetID());
+
+    auto& type = elm->GetType();
+    auto param_type_in = GetParamTypeString(ParameterType::Direction::IN, type);
+    set_get_code = ReplaceAll(set_get_code, "<PARAM_TYPE_IN>", param_type_in);
+    auto param_type_out = GetParamTypeString(ParameterType::Direction::OUT,
+        type);
+    set_get_code = ReplaceAll(set_get_code, "<PARAM_TYPE_OUT>", param_type_out);
+
+    set_get_code = ReplaceAll(set_get_code, "<BASE_SET>", GenBaseSet(elm));
+    set_get_code = ReplaceAll(set_get_code, "<BASE_GET>", GenBaseGet(elm));
+
+    code += set_get_code;
+  }
+
+  return RemoveLine(code);
 }
 
-void CBodyGeneratorBase::GenLogTag(std::ofstream& stream,
-                                   const std::string& log_tag) {
-  GenTemplate(CB_LOG_TAG, stream,
-      [&]()->std::string {
-        return log_tag;
-      });
+// @see #CB_STRUCTURE_BASE
+void CBodyGeneratorBase::GenStructureBase(std::ofstream& stream,
+    const Structure& st) {
+  std::string code = ReplaceAll(CB_STRUCTURE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", st.GetID());
+
+  auto& elms = st.GetElements();
+  code = ReplaceAll(code, "<ELEMENTS_FREE>", GenBaseElementsFree(elms));
+
+  code = ReplaceAll(code, "<PARCEL_WRITE>", GenBaseParcelWrite(elms));
+  code = ReplaceAll(code, "<PARCEL_READ>", GenBaseParcelRead(elms));
+
+  code += GenBaseSetGet(st.GetID(), elms);
+
+  stream << SmartIndent(code);
 }
 
-void CBodyGeneratorBase::GenInterfaceEnumerations(std::ofstream& stream,
-                                                  const Interface& inf) {
-  GenInterfaceMethodEnumeration(stream, inf);
-  GenInterfaceDelegateEnumeration(stream, inf);
+const std::string& CBodyGeneratorBase::GetParcelType(const BaseType& type) {
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array")
+    return parcel_type_map_["none"];
+
+  return parcel_type_map_[type.ToString()];
 }
 
-bool CBodyGeneratorBase::HasDelegate(const Interface& inf) const {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() == Declaration::MethodType::DELEGATE) {
-      return true;
+bool CBodyGeneratorBase::HasListFile(const Interface& inf) {
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (IsProxy() && d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    for (auto& p : d->GetParameters().GetParams()) {
+      auto& param_type = p->GetParameterType();
+      auto& type = param_type.GetBaseType();
+      auto name = GetFullNameFromType(type, inf);
+      if (name == "list_file")
+        return true;
     }
   }
 
   return false;
 }
 
-void CBodyGeneratorBase::GenInterfaceDelegateEnumeration(
-    std::ofstream& stream, const Interface& inf) {
-  int count = 1;
+// @see #CB_PRIVATE_SHARING_LIST_SET
+void CBodyGeneratorBase::GenPrivateSharingListSet(std::ofstream& stream) {
+  bool has_list_file = false;
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
 
-  if (!HasDelegate(inf))
-    return;
+    auto& inf = static_cast<const Interface&>(*i);
+    has_list_file = HasListFile(inf);
+    if (has_list_file)
+      break;
+  }
 
-  stream << SmartIndent(GenTemplateString(CB_DELEGATE_ENUM,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : inf.GetDeclarations().GetDecls()) {
-            if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
-              continue;
-
-            str += GenTemplateString(CB_DELEGATE_ENUM_FORMAT,
-                [&]()->std::string {
-                  return GetInterfaceIdWithNamespace(inf);
-                },
-                [&]()->std::string {
-                  return i->GetID();
-                },
-                [&]()->std::string {
-                  return std::to_string(count++);
-                });
-          }
-          return str;
-        }));
-}
+  if (!has_list_file)
+    return;
 
-void CBodyGeneratorBase::GenInterfaceMethodEnumeration(
-    std::ofstream& stream, const Interface& inf) {
-  stream << SmartIndent(GenTemplateString(CB_METHOD_ENUM,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : inf.GetDeclarations().GetDecls()) {
-            if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
-              continue;
-            str += GenTemplateString(CB_METHOD_ENUM_FORMAT,
-                [&]()->std::string {
-                  return GetInterfaceIdWithNamespace(inf);
-                },
-                [&]()->std::string {
-                  return i->GetID();
-                });
-          }
-          return str;
-        }));
-}
+  stream << SmartIndent(std::string(CB_PRIVATE_SHARING_LIST_SET));
+}
+
+// @see #CB_LIST_FILE_SET_PRIVATE_SHARING
+// @see #CB_ARRAY_FILE_SET_PRIVATE_SHARING
+// @see #CB_FILE_SET_PRIVATE_SHARING
+std::string CBodyGeneratorBase::GetPrivateSharingString(const BaseType& type,
+    const Interface& inf, const std::string& port, const std::string& arg) {
+  std::string code;
+  std::string name = GetFullNameFromType(type, inf);
+  if (name == "list_file") {
+    code = ReplaceAll(CB_LIST_FILE_SET_PRIVATE_SHARING, "<PORT>", port);
+    code = ReplaceAll(code, "<ARG>", arg);
+  } else if (name == "array_file") {
+    code = ReplaceAll(CB_ARRAY_FILE_SET_PRIVATE_SHARING, "<PORT>", port);
+    code = ReplaceAll(code, "<ARG>", arg);
+  } else if (name == "file") {
+    code = ReplaceAll(CB_FILE_SET_PRIVATE_SHARING, "<PORT>", port);
+    code = ReplaceAll(code, "<ARG>", arg);
+  }
 
-void CBodyGeneratorBase::GenLogDefinition(std::ofstream& stream) {
-  stream << SmartIndent(CB_LOG_DEF);
+  return code;
 }
 
 }  // namespace tidl
index 7de8246..03c7476 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 - 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.
@@ -30,58 +30,49 @@ class CBodyGeneratorBase : public CGeneratorBase {
   explicit CBodyGeneratorBase(std::shared_ptr<Document> doc);
   virtual ~CBodyGeneratorBase() = default;
 
+  void GenStructureDefs(std::ofstream& stream);
   void GenStructures(std::ofstream& stream);
   void GenIncludeHeader(std::ofstream& stream);
   void GenLogTag(std::ofstream& stream, const std::string& log_tag);
-  void GenInterfaceEnumerations(std::ofstream& stream, const Interface& inf);
-  std::string GetParcelWriteFunctionString(const BaseType& type,
-                                           bool meta_type = false);
-  std::string GetParcelReadFunctionString(const BaseType& type,
-                                          bool meta_type = false);
-  std::string GetDestructorString(const BaseType& type,
-                                  const std::string& value,
-                                  bool container_value = false);
-  std::string GetConstructorString(const BaseType& type,
-                                   const std::string& value);
-  bool HasDelegate(const Interface& inf) const;
   void GenLogDefinition(std::ofstream& stream);
+  void GenBaseDefinition(std::ofstream& stream);
+  const std::string& GetParcelType(const BaseType& type);
 
- private:
-  void GenInterfaceMethodEnumeration(std::ofstream& stream,
-                                     const Interface& inf);
-  void GenInterfaceDelegateEnumeration(std::ofstream& stream,
-                                       const Interface& inf);
+  void GenPrivateSharingListSet(std::ofstream& stream);
+  std::string GetPrivateSharingString(const BaseType& type,
+      const Interface& inf, const std::string& port, const std::string& arg);
 
  private:
+  void GenStructureDef(std::ofstream& stream, const Structure& st);
+  void GenStructureBaseDef(std::ofstream& stream, const Structure& st);
+  void GenStructureArrayDef(std::ofstream& stream, const Structure& st);
+  void GenStructureListDef(std::ofstream& stream, const Structure& st);
+
   void GenStructure(std::ofstream& stream, const Structure& st);
-  void GenStructureDeclaration(std::ofstream& stream, const Structure& st);
-  void GenStructureParcelSerializer(std::ofstream& stream, const Structure& st);
-  void GenStructureParcelDeserializer(std::ofstream& stream,
-                                      const Structure& st);
-  void GenStructureConstructor(std::ofstream& stream, const Structure& st);
-  void GenStructureDestructor(std::ofstream& stream, const Structure& st);
-  void GenStructureSetter(std::ofstream& stream, const Structure& st);
-  void GenStructureGetter(std::ofstream& stream, const Structure& st);
-  void GenStructureIterator(std::ofstream& stream, const Structure& st);
-  void GenStructureCloner(std::ofstream& stream, const Structure& st);
-  void GenStructureRemover(std::ofstream& stream, const Structure& st);
-  void GenStructureLengthGetter(std::ofstream& stream, const Structure& st);
+  void GenStructureBase(std::ofstream& stream, const Structure& st);
+  void GenStructureArrayBase(std::ofstream& stream, const Structure& st);
+  void GenStructureListBase(std::ofstream& stream, const Structure& st);
 
- private:
-  std::string GetParcelTypeString(const BaseType& type, bool meta_type);
-  std::string GetParcelWriteString(const std::string& id, const BaseType& type);
-  std::string GetParcelReadString(const std::string& id, const BaseType& type);
-  std::string GetFinalizeString(const std::string& id, const BaseType& type,
-                                const std::string& handle);
-  std::string GetSetterString(const std::string& id, const BaseType& type);
-  std::string GetGetterString(const std::string& id, const BaseType& type);
-  std::string GetIteratorString(const std::string& id, const BaseType& type);
-  std::string GetClonerString(const std::string& id, const BaseType& type,
-                              const Structure& st);
-  std::string GetSetterString(const BaseType& type, const std::string& lvalue,
-                              const std::string& rvalue);
-  std::string GetSetterString(const std::string& lvalue,
-                              const std::string& rvalue);
+  std::string GenArrayParcelWrite(const std::unique_ptr<Element>& elm);
+  std::string GenArrayParcelRead(const std::unique_ptr<Element>& elm);
+  std::string GenArrayElementsFree(const std::unique_ptr<Element>& elm);
+
+  std::string GenListDataFree(const std::unique_ptr<Element>& elm);
+  std::string GenListParcelWrite(const std::unique_ptr<Element>& elm);
+  std::string GenListParcelRead(const std::unique_ptr<Element>& elm);
+  std::string GenListAdd(const std::unique_ptr<Element>& elm);
+  std::string GenListCallbackParamType(const std::unique_ptr<Element>& elm);
+
+  std::string GenBaseElements(const Elements& elms);
+  std::string GenBaseElementFree(const std::unique_ptr<Element>& elm);
+  std::string GenBaseElementsFree(const Elements& elms);
+  std::string GenBaseParcelWrite(const Elements& elms);
+  std::string GenBaseParcelRead(const Elements& elms);
+  std::string GenBaseSetGet(const std::string& name, const Elements& elms);
+  std::string GenBaseSet(const std::unique_ptr<Element>& elm);
+  std::string GenBaseGet(const std::unique_ptr<Element>& elm);
+
+  bool HasListFile(const Interface& inf);
 
  private:
   std::map<std::string, std::string> parcel_type_map_;
index e9bcc76..a8f9a67 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_BODY_GEN_BASE_CB_H_
 #define IDLC_C_GEN_C_BODY_GEN_BASE_CB_H_
 
-const char CB_STRUCT_DECL[] =
+/**
+ * <LOG_TAG> The log tag.
+ */
+constexpr const char CB_LOG_TAG[] =
 R"__c_cb(
-$$struct $$_s {
-    rpc_port_parcelable_t parcelable;$$
-};
+#undef LOG_TAG
+#define LOG_TAG "<LOG_TAG>"
 )__c_cb";
 
-const char CB_STRUCT_SERIALIZER[] =
+constexpr const char CB_LOG_DEF[] =
 R"__c_cb(
-static void __##_to(rpc_port_parcel_h parcel, void *data)
-{
-    rpc_port_##_h h = data;
+#undef _E
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 
-    if (!parcel || !h) {
-        _E("Invalid parameter");
-        return;
-    }
-$$
-}
+#undef _W
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#undef _I
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#undef _D
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
 )__c_cb";
 
-const char CB_STRUCT_DESERIALIZER[] =
+constexpr const char CB_BASE_DEF[] =
 R"__c_cb(
-static void __##_from(rpc_port_parcel_h parcel, void *data)
-{
-    rpc_port_##_h h = data;
+#ifndef nullptr
+#define nullptr NULL
+#endif
 
-    if (!parcel || !h) {
-        _E("Invalid parameter");
-        return;
-    }
-$$
-}
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+#ifndef STRING_GET
+#define STRING_GET(x) ((x) ? x : "")
+#endif
 )__c_cb";
 
-const char CB_STRUCT_CTOR[] =
+/**
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ * <ELEMENTS> Elements of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  <ELEMENTS>
+} <PREFIX>_<NAME>_t;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ * <ELEMENTS_FREE> The implementation to release elements of the structure.
+ * <PARCEL_WRITE> The implementation to write the data to the parcel.
+ * <PARCEL_READ> The implementation to read the data from the parcel.
+ */
+constexpr const char CB_STRUCTURE_BASE[] =
 R"__c_cb(
-int rpc_port_##_create(rpc_port_##_h *h)
+static void __<PREFIX>_<NAME>_to(rpc_port_parcel_h parcel, void *data)
 {
-    struct ##_s *handle;
+  <PREFIX>_<NAME>_h h = data;
 
-    if (!h) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
 
-    handle = calloc(1, sizeof(struct ##_s));
-    if (!handle) {
-        _E("Out of memory");
-        return -1;
-    }
+  <PARCEL_WRITE>
+}
+
+static void __<PREFIX>_<NAME>_from(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
 
-    handle->parcelable.to = __##_to;
-    handle->parcelable.from = __##_from;
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
 
-    *h = handle;
+  <PARCEL_READ>
 
-    return 0;
+  set_last_result(RPC_PORT_ERROR_NONE);
 }
-)__c_cb";
 
-const char CB_STRUCT_DTOR[] =
-R"__c_cb(
-int rpc_port_##_destroy(rpc_port_##_h h)
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h)
 {
-    if (!h) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  <PREFIX>_<NAME>_t *handle;
 
-$$
-    free(h);
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    return 0;
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->parcelable.to = __<PREFIX>_<NAME>_to;
+  handle->parcelable.from = __<PREFIX>_<NAME>_from;
+
+  *h = handle;
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_STRUCT_SETTER[] =
-R"__c_cb(
-int rpc_port_$$_$$_$$(rpc_port_$$_h h, $$$$)
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h)
 {
-    if ($$) {
-        _E("Invalid parameter");
-        return -1;
-    }
-$$
-    return 0;
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <ELEMENTS_FREE>
+
+  free(h);
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_STRUCT_GETTER[] =
-R"__c_cb(
-int rpc_port_$$_get_$$(rpc_port_$$_h h, $$$$)
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone)
 {
-    if (!h || $$) {
-        _E("Invalid parameter");
-        return -1;
-    }
-$$
-    return 0;
+  <PREFIX>_<NAME>_h handle;
+  rpc_port_parcel_h parcel;
+  int ret;
+
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = <PREFIX>_<NAME>_create(&handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    return ret;
+  }
+
+  ret = rpc_port_parcel_create(&parcel);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  rpc_port_parcel_write(parcel, &h->parcelable, h);
+  rpc_port_parcel_read(parcel, &handle->parcelable, handle);
+  ret = get_last_result();
+  rpc_port_parcel_destroy(parcel);
+
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read data. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  *clone = handle;
+
+  return RPC_PORT_ERROR_NONE;
 }
 )__c_cb";
 
-const char CB_STRUCT_ITERATOR[] =
+/**
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ * <PARAM_TYPE_IN> The type of the input paramter.
+ * <PARAM_TYPE_OUT> The type of the output parameter.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ * <BASE_SET> The implementation to set the data to the structure.
+ * <BASE_GET> The implementation to get the data from the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_SET_GET[] =
 R"__c_cb(
-int rpc_port_$$_foreach_$$(rpc_port_$$_h h,
-        bool (*callback)($$$$, void *user_data), void *user_data)
+int <PREFIX>_<NAME>_set_<ELEMENT_NAME>(<PREFIX>_<NAME>_h h, <PARAM_TYPE_IN>value)
 {
-    if (!h || !callback) {
-        _E("Invalid parameter");
-        return -1;
-    }
-$$
-    return 0;
+  <BASE_SET>
 }
-)__c_cb";
 
-const char CB_STRUCT_REMOVER[] =
-R"__c_cb(
-int rpc_port_$$_remove_$$(rpc_port_$$_h h, unsigned int nth)
+int <PREFIX>_<NAME>_get_<ELEMENT_NAME>(<PREFIX>_<NAME>_h h, <PARAM_TYPE_OUT>value)
 {
-    GList *iter;
+  <BASE_GET>
+}
+)__c_cb";
 
-    if (!h) {
-        _E("Invalid parameter");
-        return -1;
-    }
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write(parcel, &h-><ELEMENT_NAME>->parcelable, h-><ELEMENT_NAME>);
+)__c_cb";
 
-    iter = g_list_nth(h->$$, nth);
-    if (iter == NULL)
-        return -1;
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BUNDLE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_bundle(parcel, h-><ELEMENT_NAME>);
+)__c_cb";
 
-    $$value = iter->data;
-    h->$$ = g_list_remove_link(h->$$, iter);
-$$
-    g_list_free(iter);
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_STRING_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_string(parcel, STRING_GET(h-><ELEMENT_NAME>));
+)__c_cb";
 
-    return 0;
-}
+/**
+ * <PARCEL_TYPE> The type of the parcel of the element.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BASE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel, h-><ELEMENT_NAME>);
 )__c_cb";
 
-const char CB_STRUCT_LENGTH_GETTER[] =
+/**
+ * <PREFIX> The prefix of the element type.
+ * <NAME> The name of the element type.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_READ[] =
 R"__c_cb(
-int rpc_port_$$_get_$$_length(rpc_port_$$_h h, unsigned int *length)
-{
-    if (!h || !length) {
-        _E("Invalid parameter");
-        return -1;
-    }
+<PREFIX>_<NAME>_create(&h-><ELEMENT_NAME>);
+if (h-><ELEMENT_NAME> == nullptr) {
+  _E("Failed to create handle");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
+}
 
-    *length = g_list_length(h->$$);
+rpc_port_parcel_read(parcel, &h-><ELEMENT_NAME>->parcelable, h-><ELEMENT_NAME>);
+if (get_last_result() != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data");
+  return;
+}
+)__c_cb";
 
-    return 0;
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BUNDLE_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_bundle(parcel, &h-><ELEMENT_NAME>);
+if (h-><ELEMENT_NAME> == nullptr) {
+  _E("Failed to read data");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
 }
 )__c_cb";
 
-const char CB_STRUCT_CLONER[] =
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_STRING_PARCEL_READ[] =
 R"__c_cb(
-int rpc_port_##_clone(rpc_port_##_h h, rpc_port_##_h *clone)
-{
-    rpc_port_##_h handle = NULL;
-
-    if (!h || !clone) {
-        _E("Invalid parameter");
-        return -1;
-    }
-
-    rpc_port_##_create(&handle);
-    if (!handle) {
-        _E("Failed to create ## handle");
-        return -1;
-    }
-$$
-    *clone = handle;
-
-    return 0;
+rpc_port_parcel_read_string(parcel, &h-><ELEMENT_NAME>);
+if (h-><ELEMENT_NAME> == nullptr) {
+  _E("Failed to read data");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
 }
 )__c_cb";
 
-const char CB_WRITE_LIST_BLOCK[] =
+/**
+ * <PARCEL_TYPE> The type of the parcel of the element.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BASE_PARCEL_READ[] =
 R"__c_cb(
-do {
-    GList *iter;
+rpc_port_parcel_read_<PARCEL_TYPE>(parcel, &h-><ELEMENT_NAME>);
+)__c_cb";
 
-    iter = $$;
-    while (iter) {
-        $$value = iter->data;
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ * <PREFIX> The prefix of the element type.
+ * <NAME> The name of the element type.
+ */
+constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_FREE[] =
+R"__c_cb(
+if (h-><ELEMENT_NAME>)
+  <PREFIX>_<NAME>_destroy(h-><ELEMENT_NAME>);
+)__c_cb";
 
-        iter = g_list_next(iter);
-        if (!value) {
-            _W("Warning: value is NULL");
-            continue;
-        }
-        $$
-    }
-} while (0);
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BUNDLE_FREE[] =
+R"__c_cb(
+if (h-><ELEMENT_NAME>)
+  bundle_free(h-><ELEMENT_NAME>);
 )__c_cb";
 
-const char CB_WRITE_ARRAY_BLOCK[] =
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_STRING_FREE[] =
 R"__c_cb(
-do {
-    for (int i = 0; i < $$; i++) {
-$$
-    }
-} while (0);
+if (h-><ELEMENT_NAME>)
+  free(h-><ELEMENT_NAME>);
 )__c_cb";
 
-const char CB_READ_LIST_BLOCK[] =
-R"__c_cb(do {
-    int len = 0;
+/**
+ * <PREFIX> The prefix of the element type.
+ * <NAME> The name of the element type.
+ * <ELEMENT_FREE> The implementation to release the element of the structure.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ * @see #CB_STRUCTURE_BASE_USER_DEFINED_FREE
+ */
+constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_SET[] =
+R"__c_cb(
+<PREFIX>_<NAME>_h new_value;
+int ret;
+
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+ret = <PREFIX>_<NAME>_clone(value, &new_value);
+if (ret != RPC_PORT_ERROR_NONE) {
+  _E("Failed to clone handle. error(%d)", ret);
+  return ret;
+}
+
+<ELEMENT_FREE>
 
-    $$
-    for (int i = 0; i < len; i++) {
-        $$value = NULL;
+h-><ELEMENT_NAME> = new_value;
 
-        $$
-        $$ = g_list_append($$, value);
-    }
-} while (0);
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_READ_ARRAY_BLOCK[] =
+/**
+ * <ELEMENT_FREE> The implementation to release the element of the structure.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ * @see #CB_STRUCTURE_BASE_BUNDLE_FREE
+ */
+constexpr const char CB_STRUCTURE_BASE_BUNDLE_SET[] =
 R"__c_cb(
-do {
-    $$
+bundle *new_value;
 
-    h->## = calloc(h->##_size, sizeof(*h->##));
-    if (!h->##) {
-        _E("Out of memory");
-        return;
-    }
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
 
-    for (int i = 0; i < h->##_size; i++) {
-        $$value = $$;
+new_value = bundle_dup(value);
+if (new_value == nullptr) {
+  _E("Failed to duplicate value");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
 
-        $$
-    }
-} while (0);
-)__c_cb";
+<ELEMENT_FREE>
 
-const char CB_READ_USER_DEFINED_BLOCK[] =
-R"__c_cb(do {
-    rpc_port_$$_create(&h->##);
-    if (!h->##) {
-        _E("Failed to create handle");
-        return;
-    }
+h-><ELEMENT_NAME> = new_value;
 
-    rpc_port_parcel_read(parcel, &h->##->parcelable, h->##);
-} while (0);
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_FINALIZE_LIST_BLOCK[] =
+/**
+ * <ELEMENT_FREE> The implementation to release the element of the structure.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ * @see #CB_STRUCTURE_BASE_STRING_FREE
+ */
+constexpr const char CB_STRUCTURE_BASE_STRING_SET[] =
 R"__c_cb(
-do {
-    GList *iter;
-
-    iter = $$;
-    while (iter) {
-        $$value = iter->data;
-        $$
-        iter = g_list_next(iter);
-    }
-    g_list_free($$);
-} while (0);
-)__c_cb";
+char *new_value;
 
-const char CB_FINALIZE_ARRAY_BLOCK[] =
-R"__c_cb(
-do {
-    for (int j = 0; j < $$; j++) {
-        $$
-    }
-    free($$);
-} while (0);
-)__c_cb";
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
 
-const char CB_SETTER_LIST_BLOCK[] =
-R"__c_cb(
-do {
-    $$value = NULL;
+new_value = strdup(value);
+if (new_value == nullptr) {
+  _E("Failed to duplicate value");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
 
-    $$
-    $$ = g_list_append($$, value);
-} while (0);
-)__c_cb";
+<ELEMENT_FREE>
 
-const char CB_SETTER_ARRAY_BLOCK[] =
-R"__c_cb(
-do {
-    h->## = calloc(##_size, sizeof(*##));
-    if (!h->##) {
-        _E("Out of memory");
-        return -1;
-    }
-    h->##_size = ##_size;
-
-    for (int i = 0; i < h->##_size; i++) {
-        $$
-    }
-} while (0);
+h-><ELEMENT_NAME> = new_value;
+
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_GETTER_ARRAY_BLOCK[] =
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BASE_SET[] =
 R"__c_cb(
-do {
-    if (h->##_size == 0) {
-        _W("## is empty");
-        break;
-    }
-
-    *## = calloc(h->##_size, sizeof(*h->##));
-    if (!*##) {
-        _E("Out of memory");
-        return -1;
-    }
-    *##_size = h->##_size;
-
-    for (int i = 0; i < h->##_size; i++) {
-        $$
-    }
-} while (0);
+if (h == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+h-><ELEMENT_NAME> = value;
+
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_ITERATOR_BLOCK[] =
+/**
+ * <PREFIX> The prefix of the element type.
+ * <NAME> The name of the element type.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_GET[] =
 R"__c_cb(
-do {
-    GList *iter;
+<PREFIX>_<NAME>_h new_value;
+int ret;
 
-    iter = $$;
-    while (iter) {
-        $$value = iter->data;
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
 
-        iter = g_list_next(iter);
-        if (!value) {
-            _W("Warning: value is NULL");
-            continue;
-        }
+if (h-><ELEMENT_NAME> == nullptr) {
+  _E("<ELEMENT_NAME> is nullptr");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
 
-        bool ret = callback($$, user_data);
-        if (!ret)
-            break;
-    }
-} while (0);
-)__c_cb";
+ret = <PREFIX>_<NAME>_clone(h-><ELEMENT_NAME>, &new_value);
+if (ret != RPC_PORT_ERROR_NONE) {
+  _E("Failed to clone handle. error(%d)", ret);
+  return ret;
+}
 
-const char CB_CLONER_LIST_BLOCK[] =
-R"__c_cb(
-do {
-    GList *iter;
-
-    iter = $$;
-    while (iter) {
-        $$new_value;
-        $$value = iter->data;
-
-        if (!value) {
-            _E("Error: value is NULL");
-            rpc_port_$$_destroy(handle);
-            return -1;
-        }
+*value = new_value;
 
-        $$
-        $$ = g_list_append($$, new_value);
-        iter = g_list_next(iter);
-    }
-} while (0);
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_CLONER_ARRAY_BLOCK[] =
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BUNDLE_GET[] =
 R"__c_cb(
-do {
-    if (h->##_size == 0) {
-        _W("## is empty");
-        break;
-    }
-
-    handle->## = calloc(h->##_size, sizeof(*h->##));
-    if (!handle->##) {
-        _E("Out of memory");
-        rpc_port_$$_destroy(handle);
-        return -1;
-    }
-    handle->##_size = h->##_size;
-
-    for (int i = 0; i < h->##_size; i++) {
-        $$
-    }
-} while (0);
-)__c_cb";
+bundle *new_value;
 
-const char CB_IF_STATEMENT_WITH_BRACES[] =
-R"__c_cb(if ($$) {
-    $$
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
 }
-)__c_cb";
 
-const char CB_IF_STATEMENT[] =
-R"__c_cb(if ($$)
-    $$
-)__c_cb";
+if (h-><ELEMENT_NAME> == nullptr) {
+  _E("<ELEMENT_NAME> is nullptr");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
 
-const char CB_DELEGATE_ENUM_FORMAT[] = "\n$$_DELEGATE_$$ = $$,";
+new_value = bundle_dup(h-><ELEMENT_NAME>);
+if (new_value == nullptr) {
+  _E("Failed to duplicate value");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
 
-const char CB_DELEGATE_ENUM[] =
-R"__c_cb(
-enum $$_delegate_e {$$
-};
-)__c_cb";
+*value = new_value;
 
-const char CB_METHOD_ENUM_FORMAT[] = "\n$$_METHOD_$$,";
+return RPC_PORT_ERROR_NONE;
+)__c_cb";
 
-const char CB_METHOD_ENUM[] =
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_STRING_GET[] =
 R"__c_cb(
-enum $$_method_e {
-    $$_METHOD_Result,
-    $$_METHOD_Callback,$$
-};
+char *new_value;
+
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+if (h-><ELEMENT_NAME> == nullptr) {
+  _E("<ELEMENT_NAME> is nullptr");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+new_value = strdup(h-><ELEMENT_NAME>);
+if (new_value == nullptr) {
+  _E("Failed to duplicate value");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+*value = new_value;
+
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_LOG_TAG[] =
+/**
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_BASE_GET[] =
 R"__c_cb(
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
 
-#define LOG_TAG "$$"
+*value = h-><ELEMENT_NAME>;
+
+return RPC_PORT_ERROR_NONE;
 )__c_cb";
 
-const char CB_LOG_DEF[] =
+constexpr const char CB_PRIVATE_SHARING_LIST_SET[] =
 R"__c_cb(
-#ifdef _E
-#undef _E
-#endif
+static int __rpc_port_set_private_sharing_list(rpc_port_h port, GList *list)
+{
+        const char **array_file;
+        const char *value;
+        guint size;
+        GList *iter;
+        int idx = 0;
+        int ret;
+
+        size = g_list_length(list);
+        if (size == 0) {
+                _E("Invalid parameter");
+                return RPC_PORT_ERROR_INVALID_PARAMETER;
+        }
 
-#ifdef _W
-#undef _W
-#endif
+        array_file = calloc(size, sizeof(const char*));
+        if (array_file == nullptr) {
+                _E("Out of memory");
+                return RPC_PORT_ERROR_OUT_OF_MEMORY;
+        }
 
-#ifdef _I
-#undef _I
-#endif
+        iter = list;
+        while (iter) {
+                value = iter->data;
+                array_file[idx++] = value;
+                iter = g_list_next(iter);
+        }
 
-#ifdef _D
-#undef _D
-#endif
+        ret = rpc_port_set_private_sharing_array(port, array_file, idx);
+        free(array_file);
 
-#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+        return ret;
+}
+)__c_cb";
+
+/**
+ * <PORT> The rpc port handle.
+ * <ARG> The argument.
+ */
+constexpr const char CB_LIST_FILE_SET_PRIVATE_SHARING[] =
+R"__c_cb(
+__rpc_port_set_private_sharing_list(<PORT>, <ARG>->list);
+)__c_cb";
+
+/**
+ * <PORT> The rpc port handle.
+ * <ARG> The argument.
+ */
+constexpr const char CB_ARRAY_FILE_SET_PRIVATE_SHARING[] =
+R"__c_cb(
+rpc_port_set_private_sharing_array(<PORT>, (const char **)<ARG>->value, <ARG>->size);
+)__c_cb";
+
+/**
+ * <PORT> The rpc port handle.
+ * <ARG> The argument.
+ */
+constexpr const char CB_FILE_SET_PRIVATE_SHARING[] =
+R"__c_cb(
+rpc_port_set_private_sharing(<PORT>, <ARG>);
 )__c_cb";
 
 #endif  // IDLC_C_GEN_C_BODY_GEN_BASE_CB_H_
diff --git a/idlc/gen/c_body_gen_list_base_cb.h b/idlc/gen/c_body_gen_list_base_cb.h
new file mode 100644 (file)
index 0000000..d0e5ddf
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * 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_C_GEN_C_BODY_GEN_LIST_BASE_CB_H_
+#define IDLC_C_GEN_C_BODY_GEN_LIST_BASE_CB_H_
+
+/**
+ * <PREFIX> The prefix of the list structure.
+ * <NAME> The name of the list structure.
+ */
+constexpr const char CB_STRUCTURE_LIST_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  GList *list;
+} <PREFIX>_<NAME>_t;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the list structure.
+ * <NAME> The name of the list structure.
+ * <DATA_TYPE> The type of the data of the list.
+ * <DATA_FREE> The implementation to release the data of the list.
+ * <PARAM_TYPE_IN> The type of the parameter of the add function.
+ * <PARCEL_WRITE> The implementation to write the data to parcel.
+ * <PARCEL_READ> The implementation to read the data from the parcel.
+ * <LIST_ADD> The implementation to add the data to the list.
+ * <CALLBACK_PARAM_TYPE> The type of the parameter of the callback.
+ */
+constexpr const char CB_STRUCTURE_LIST_BASE[] =
+R"__c_cb(
+static void __<PREFIX>_<NAME>_to(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  <DATA_TYPE>value;
+  GList *iter;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
+
+  rpc_port_parcel_write_array_count(parcel, g_list_length(h->list));
+
+  iter = h->list;
+  while (iter) {
+    value = iter->data;
+    iter = g_list_next(iter);
+    <PARCEL_WRITE>
+  }
+}
+
+static void __<PREFIX>_<NAME>_from(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  <DATA_TYPE>value = nullptr;
+  int ret;
+  int len = 0;
+  int i;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  ret = rpc_port_parcel_read_array_count(parcel, &len);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read array count. error(%d)", ret);
+    set_last_result(ret);
+    return;
+  }
+
+  for (i = 0; i < len; ++i) {
+    <PARCEL_READ>
+  }
+
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h)
+{
+  <PREFIX>_<NAME>_t *handle;
+
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->parcelable.to = __<PREFIX>_<NAME>_to;
+  handle->parcelable.from = __<PREFIX>_<NAME>_from;
+
+  *h = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h)
+{
+  <DATA_TYPE>value;
+  GList *iter;
+
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  if (h->list) {
+    iter = h->list;
+    while (iter) {
+      value = iter->data;
+      iter = g_list_next(iter);
+      <DATA_FREE>
+    }
+
+    g_list_free(h->list);
+  }
+
+  free(h);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone)
+{
+  <PREFIX>_<NAME>_h handle;
+  rpc_port_parcel_h parcel;
+  int ret;
+
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = <PREFIX>_<NAME>_create(&handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    return ret;
+  }
+
+  ret = rpc_port_parcel_create(&parcel);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  rpc_port_parcel_write(parcel, &h->parcelable, h);
+  rpc_port_parcel_read(parcel, &handle->parcelable, handle);
+  ret = get_last_result();
+  rpc_port_parcel_destroy(parcel);
+
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read data. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  *clone = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_add(<PREFIX>_<NAME>_h h, <PARAM_TYPE_IN>value)
+{
+  <LIST_ADD>
+}
+
+int <PREFIX>_<NAME>_foreach(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_cb callback, void *user_data)
+{
+  <DATA_TYPE>value;
+  GList *iter;
+
+  if (h == nullptr || callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  iter = h->list;
+  while (iter) {
+    value = iter->data;
+    iter = g_list_next(iter);
+    if (!callback(<CALLBACK_PARAM_TYPE>, user_data))
+      break;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remove(<PREFIX>_<NAME>_h h, unsigned int nth)
+{
+  <DATA_TYPE>value;
+  GList *found;
+
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  found = g_list_nth(h->list, nth);
+  if (found == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  value = found->data;
+  h->list = g_list_remove_link(h->list, found);
+  <DATA_FREE>
+  g_list_free(found);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_length(<PREFIX>_<NAME>_h h, unsigned int *length)
+{
+  if (h == nullptr || length == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  *length = g_list_length(h->list);
+
+  return RPC_PORT_ERROR_NONE;
+}
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write(parcel, &value->parcelable, value);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_BUNDLE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_bundle(parcel, value);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_STRING_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_string(parcel, STRING_GET(value));
+)__c_cb";
+
+/**
+ * <PARCEL_TYPE> The type of the parcel of the value.
+ */
+constexpr const char CB_STRUCTURE_LIST_BASE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel, *value);
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user-defined type.
+ * <NAME> The name of the user-defined type.
+ */
+constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_READ[] =
+R"__c_cb(
+ret = <PREFIX>_<NAME>_create(&value);
+if (ret != RPC_PORT_ERROR_NONE) {
+  _E("Failed to create handle. error(%d)", ret);
+  set_last_result(ret);
+  return;
+}
+
+rpc_port_parcel_read(parcel, &value->parcelable, value);
+if (get_last_result() != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data. error(%d)", get_last_result());
+  <PREFIX>_<NAME>_destroy(value);
+  return;
+}
+
+h->list = g_list_append(h->list, value);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_BUNDLE_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_bundle(parcel, &value);
+if (value == nullptr) {
+  _E("Failed to read data");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
+}
+
+h->list = g_list_append(h->list, value);
+value = nullptr;
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_STRING_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_string(parcel, &value);
+if (value == nullptr) {
+  _E("Failed to read data");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
+}
+
+h->list = g_list_append(h->list, value);
+value = nullptr;
+)__c_cb";
+
+/**
+ * <VALUE_TYPE> The type of the value.
+ * <PARCEL_TYPE> The type of the parcel of the value.
+ */
+constexpr const char CB_STRUCTURE_LIST_BASE_PARCEL_READ[] =
+R"__c_cb(
+value = calloc(1, sizeof(sizeof(<VALUE_TYPE>)));
+if (value == nullptr) {
+  _E("Out of memory");
+  set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+  return;
+}
+
+rpc_port_parcel_read_<PARCEL_TYPE>(parcel, value);
+
+h->list = g_list_append(h->list, value);
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user-defined type.
+ * <NAME> The name of the user-defined type.
+ */
+constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_ADD[] =
+R"__c_cb(
+<PREFIX>_<NAME>_h new_value;
+int ret;
+
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+ret = <PREFIX>_<NAME>_clone(value, &new_value);
+if (ret != RPC_PORT_ERROR_NONE)
+  return ret;
+
+h->list = g_list_append(h->list, new_value);
+
+return RPC_PORT_ERROR_NONE;
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_BUNDLE_ADD[] =
+R"__c_cb(
+bundle *new_value;
+
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+new_value = bundle_dup(value);
+if (new_value == nullptr) {
+  _E("Failed to duplicate value");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+h->list = g_list_append(h->list, new_value);
+
+return RPC_PORT_ERROR_NONE;
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_STRING_ADD[] =
+R"__c_cb(
+char *new_value;
+
+if (h == nullptr || value == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+new_value = strdup(value);
+if (new_value == nullptr) {
+  _E("Failed to duplicate value");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+h->list = g_list_append(h->list, new_value);
+
+return RPC_PORT_ERROR_NONE;
+)__c_cb";
+
+/**
+ * <VALUE_TYPE> The type of the value.
+ */
+constexpr const char CB_STRUCTURE_LIST_BASE_ADD[] =
+R"__c_cb(
+<VALUE_TYPE>*new_value;
+
+if (h == nullptr) {
+  _E("Invalid parameter");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+new_value = calloc(1, sizeof(<VALUE_TYPE>));
+if (new_value == nullptr) {
+  _E("Out of memory");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+*new_value = value;
+
+h->list = g_list_append(h->list, new_value);
+
+return RPC_PORT_ERROR_NONE;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user-defined type.
+ * <NAME> The name of the user-defined type.
+ */
+constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_FREE[] =
+R"__c_cb(
+<PREFIX>_<NAME>_destroy(value);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_BUNDLE_FREE[] =
+R"__c_cb(
+bundle_free(value);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_STRING_FREE[] =
+R"__c_cb(
+free(value);
+)__c_cb";
+
+constexpr const char CB_STRUCTURE_LIST_BASE_FREE[] =
+R"__c_cb(
+free(value);
+)__c_cb";
+
+#endif  // IDLC_C_GEN_C_BODY_GEN_LIST_BASE_CB_H_
index b3fe325..f53be99 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 
 namespace {
 #include "idlc/gen/c_gen_base_cb.h"
-}
+
+constexpr const char PREFIX_RPC_PORT_PROXY[] = "rpc_port_proxy";
+constexpr const char PREFIX_RPC_PORT_STUB[] = "rpc_port_stub";
+
+}  // namespace
 
 namespace tidl {
 
@@ -32,84 +36,72 @@ CGeneratorBase::CGeneratorBase(std::shared_ptr<Document> doc)
     : Generator(doc) {
   structures_.clear();
   type_map_ = {
-      {"char", "char "}, {"int", "int "}, {"short", "short "},
-      {"long", "long long "}, {"bool", "bool "}, {"string", "char *"},
-      {"list", "GList *"}, {"float", "float "}, {"double", "double "},
-      {"bundle", "bundle *"}, {"void", "void "}, {"file", "char *"}
+      {"char", "char "},
+      {"int", "int "},
+      {"short", "short "},
+      {"long", "long long "},
+      {"bool", "bool "},
+      {"string", "char *"},
+      {"list", "GList *"},
+      {"float", "float "},
+      {"double", "double "},
+      {"bundle", "bundle *"},
+      {"void", "void "},
+      {"file", "char *"}
   };
 }
 
 std::string CGeneratorBase::Tab(int cnt) {
   std::string str;
-
-  for (int i = 0; i < cnt; ++i) {
+  for (int i = 0; i < cnt; ++i)
     str += "\t";
-  }
 
   return str;
 }
 
 std::string CGeneratorBase::NLine(int cnt) {
   std::string str;
-
-  for (int i = 0; i < cnt; ++i) {
+  for (int i = 0; i < cnt; ++i)
     str += "\n";
-  }
 
   return str;
 }
 
-std::string CGeneratorBase::ConvertTypeToString(
-    ParameterType::Direction direction, const BaseType& type, bool bconst) {
-  if (type.IsUserDefinedType()) {
-    if (direction == ParameterType::Direction::IN)
-      return GetHandlePrefix() + type.ToString() + "_h ";
-    else
-      return GetHandlePrefix() + type.ToString() + "_h *";
-  }
-
-  if (type.ToString() == "array") {
-    if (direction == ParameterType::Direction::IN) {
-      return GetReturnTypeString(*type.GetMetaType()) + "*";
-    } else {
-      return GetReturnTypeString(*type.GetMetaType()) + "**";
-    }
-  }
+std::string CGeneratorBase::GetFullNameFromType(const BaseType& type) {
+  std::string str = type.ToString();
 
-  if (type.ToString() == "string" || type.ToString() == "file") {
-    if (direction == ParameterType::Direction::IN) {
-      if (!bconst)
-        return "char *";
-      return "const char *";
-    } else
-      return "char **";
+  if (type.GetMetaType() != nullptr) {
+    str += "_";
+    str += GetFullNameFromType(*type.GetMetaType());
   }
 
-  if (direction == ParameterType::Direction::IN && bconst)
-    return type_map_[type.ToString()];
-
-  return type_map_[type.ToString()] + "*";
+  return str;
 }
 
-std::string CGeneratorBase::GetFullNameFromType(const BaseType& type) {
-  std::string str = type.ToString();
+std::string CGeneratorBase::GetFullNameFromType(const BaseType& type,
+    const Interface& inf) {
+  std::string str;
+  if (IsDelegateType(inf, type))
+    str += inf.GetID() + "_";
+
+  str += type.ToString();
 
   if (type.GetMetaType() != nullptr) {
     str += "_";
-    str += GetFullNameFromType(*type.GetMetaType());
+    str += GetFullNameFromType(*type.GetMetaType(), inf);
   }
 
   return str;
 }
 
-std::string CGeneratorBase::GetParcelParamTypeString(const BaseType& type,
+std::string CGeneratorBase::GetDataTypeString(const BaseType& type,
                                                      bool is_pointer) {
   if (type.IsUserDefinedType())
-    return GetHandlePrefix() + type.ToString() + "_h ";
+    return GetHandlePrefix() + "_" + type.ToString() + "_h ";
 
   if (type.ToString() == "list" ||
       type.ToString() == "array")
-    return GetHandlePrefix() + GetFullNameFromType(type) + "_h ";
+    return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h ";
 
   if (type.ToString() == "string" || type.ToString() == "file")
     return "char *";
@@ -125,11 +117,11 @@ std::string CGeneratorBase::GetParcelParamTypeString(const BaseType& type,
 
 std::string CGeneratorBase::GetReturnTypeString(const BaseType& type) {
   if (type.IsUserDefinedType())
-    return GetHandlePrefix() + type.ToString() + "_h ";
+    return GetHandlePrefix() + "_" + type.ToString() + "_h ";
 
   if (type.ToString() == "list" ||
       type.ToString() == "array")
-    return GetHandlePrefix() + GetFullNameFromType(type) + "_h ";
+    return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h ";
 
   return type_map_[type.ToString()];
 }
@@ -138,27 +130,81 @@ void CGeneratorBase::AddStructureFromType(const BaseType& type) {
   if (type.GetMetaType() == nullptr)
     return;
 
-  BaseType* t = new BaseType(type);
+  BaseType* t = new BaseType(*type.GetMetaType());
   assert(t != nullptr);
 
   std::string type_name = GetFullNameFromType(type);
-  Element* elm = new Element(type_name + "s", t, "", __LINE__);
+  Element* elm = new Element(type_name, t, "", __LINE__);
   assert(elm != nullptr);
 
   Elements* elms = new Elements();
   assert(elms != nullptr);
   elms->Add(elm);
 
-  Structure* st = new Structure(type_name, elms, "", __LINE__);
+  auto* st = new Structure(type_name, elms, "", __LINE__);
   assert(st != nullptr);
 
-  if (StructureExist(*st)) {
+  AddStructureFromType(*type.GetMetaType());
+
+  if (StructureExist(st)) {
     delete st;
-  } else {
-    structures_[type_name] = std::unique_ptr<Structure>(st);
+    return;
   }
 
-  AddStructureFromType(*type.GetMetaType());
+  structures_[type_name] = std::unique_ptr<Structure>(st);
+}
+
+void CGeneratorBase::AddStructureFromType(const BaseType& type,
+    const Interface& inf) {
+  if (type.GetMetaType() == nullptr)
+    return;
+
+  BaseType* t = nullptr;
+  if (IsDelegateType(inf, *type.GetMetaType()))
+    t = new BaseType(GetFullNameFromType(*type.GetMetaType(), inf), "", true);
+  else
+    t = new BaseType(*type.GetMetaType());
+
+  assert(t != nullptr);
+
+  std::string type_name = GetFullNameFromType(type, inf);
+  Element* elm = new Element(type_name, t, "", __LINE__);
+  assert(elm != nullptr);
+
+  Elements* elms = new Elements();
+  assert(elms != nullptr);
+  elms->Add(elm);
+
+  auto* st = new Structure(type_name, elms, "", __LINE__);
+  assert(st != nullptr);
+
+  AddStructureFromType(*type.GetMetaType(), inf);
+
+  if (StructureExist(st)) {
+    delete st;
+    return;
+  }
+
+  structures_[type_name] = std::unique_ptr<Structure>(st);
+}
+
+std::string CGeneratorBase::RemoveLine(std::string lines,
+    unsigned int line_num) {
+  std::stringstream ss(lines);
+  std::string result;
+  std::string line;
+  unsigned int line_count = 0;
+
+  while (std::getline(ss, line, '\n')) {
+    line_count++;
+    if (line_num == line_count)
+      continue;
+
+    result += Trim(line);
+    result += NLine(1);
+  }
+
+  return result;
 }
 
 std::string CGeneratorBase::SmartIndent(std::string lines) {
@@ -175,6 +221,7 @@ std::string CGeneratorBase::SmartIndent(std::string lines) {
   int line_count = 0;
 
   while (std::getline(ss, next_line, '\n')) {
+    next_line = RemoveSpaces(next_line);
     line_count++;
     if (line_count == 1) {
       line = Trim(next_line);
@@ -187,9 +234,9 @@ std::string CGeneratorBase::SmartIndent(std::string lines) {
       tab_size--;
     }
 
-    if (line.length() > 0) {
+    back = line.back();
+    if (back != ":" && line.length() > 0)
       tab += Tab(tab_size);
-    }
 
     if (continuous && tab_size == 0 &&
         found == std::string::npos) {
@@ -202,8 +249,7 @@ std::string CGeneratorBase::SmartIndent(std::string lines) {
     }
 
     continuous = false;
-    back = line.back();
-    if (back == ",")
+    if (back == "," || back == "\\")
       continuous = true;
 
     if (line.empty() ||
@@ -221,7 +267,12 @@ std::string CGeneratorBase::SmartIndent(std::string lines) {
         result += NLine(1);
       }
     } else {
-      result += tab + line;
+      // for annotation && ifdef
+      if (line.compare(0, 2, " *") == 0 || line.compare(0, 1, "#") == 0)
+        result += line;
+      else
+        result += tab + line;
+
       result += NLine(1);
     }
 
@@ -234,6 +285,25 @@ std::string CGeneratorBase::SmartIndent(std::string lines) {
         tab_size++;
         if_statement = true;
       }
+
+      found = line.find("else");
+      if (found != std::string::npos && line != "#else") {
+        tab_size++;
+        if_statement = true;
+      }
+
+      found = line.find("for (");
+      if (found != std::string::npos) {
+        tab_size++;
+        if_statement = true;
+      }
+
+      back = line.back();
+      found = line.find("while (");
+      if (found != std::string::npos && back != ";") {
+        tab_size++;
+        if_statement = true;
+      }
     }
 
     line = Trim(next_line);
@@ -245,7 +315,35 @@ std::string CGeneratorBase::SmartIndent(std::string lines) {
   return result;
 }
 
+std::string CGeneratorBase::RemoveLastSpaces(const std::string& str) {
+  std::size_t found = str.find_last_not_of(' ');
+  if (found == std::string::npos)
+    return str;
+
+  return str.substr(0, found + 1);
+}
+
+std::string CGeneratorBase::RemoveSpaces(const std::string& str) {
+  // for annotation
+  if (str.compare(0, 3, "/**") == 0 ||
+      str.compare(0, 2, " *") == 0 ||
+      str.compare(0, 3, " */") == 0)
+    return str;
+
+  std::size_t found = str.find_first_not_of(' ');
+  if (found == std::string::npos)
+      return "";
+
+  return str.substr(found, str.size() - found);
+}
+
 std::string CGeneratorBase::Trim(const std::string& str) {
+  // for annotation
+  if (str.compare(0, 3, "/**") == 0 ||
+      str.compare(0, 2, " *") == 0 ||
+      str.compare(0, 3, " */") == 0)
+    return str;
+
   std::size_t first = str.find_first_not_of(" \t\r\n");
   if (first == std::string::npos)
     return str;
@@ -255,10 +353,7 @@ std::string CGeneratorBase::Trim(const std::string& str) {
 }
 
 void CGeneratorBase::GenVersion(std::ofstream& stream) {
-  GenTemplate(CB_VERSION, stream,
-      [&]()->std::string {
-        return FULLVER;
-      });
+  stream << ReplaceAll(CB_VERSION, "<VERSION>", FULLVER);
 }
 
 void CGeneratorBase::GenIncludeDefaultHeaders(std::ofstream& stream,
@@ -271,19 +366,19 @@ void CGeneratorBase::GenIncludeDefaultHeaders(std::ofstream& stream,
 }
 
 void CGeneratorBase::GenGNUSourceDefinition(std::ofstream& stream) {
-  stream << NLine(1);
-  stream << CB_GNU_SOURCE;
+  stream << SmartIndent(CB_GNU_SOURCE);
 }
 
-bool CGeneratorBase::StructureExist(const Structure& st) {
+bool CGeneratorBase::StructureExist(const Structure* st) {
   for (auto& i : GetDocument().GetBlocks()) {
     if (i->GetType() != Block::TYPE_STRUCTURE)
       continue;
 
     const Structure &s = static_cast<const Structure&>(*i);
-    if (s.GetID() == st.GetID())
+    if (s.GetID() == st->GetID())
       return true;
   }
+
   return false;
 }
 
@@ -293,12 +388,12 @@ std::string CGeneratorBase::GetParamTypeString(
       type.ToString() == "list" ||
       type.ToString() == "array") {
     if (direction == ParameterType::Direction::IN)
-      return GetHandlePrefix() + GetFullNameFromType(type) + "_h ";
+      return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h ";
     else
-      return GetHandlePrefix() + GetFullNameFromType(type) + "_h *";
+      return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h *";
   }
 
-  if (type.ToString() == "string") {
+  if (type.ToString() == "string" || type.ToString() == "file") {
     if (direction == ParameterType::Direction::IN)
       return "const char *";
     else
@@ -311,6 +406,41 @@ std::string CGeneratorBase::GetParamTypeString(
   return type_map_[type.ToString()] + "*";
 }
 
+std::string CGeneratorBase::GetParamTypeString(
+    ParameterType::Direction direction, const BaseType& type,
+    const Interface& inf) {
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    if (direction == ParameterType::Direction::IN)
+      return GetHandlePrefix() + "_" + GetFullNameFromType(type, inf) + "_h ";
+    else
+      return GetHandlePrefix() + "_" + GetFullNameFromType(type, inf) + "_h *";
+  }
+
+  if (type.ToString() == "string" || type.ToString() == "file") {
+    if (direction == ParameterType::Direction::IN)
+      return "const char *";
+    else
+      return "char **";
+  }
+
+  if (direction == ParameterType::Direction::IN)
+    return type_map_[type.ToString()];
+
+  return type_map_[type.ToString()] + "*";
+}
+
+std::string CGeneratorBase::GetArgTypeString(const BaseType& type,
+    const Interface& inf) {
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array")
+    return GetHandlePrefix() + "_" + GetFullNameFromType(type, inf) + "_h ";
+
+  return type_map_[type.ToString()];
+}
+
 std::string CGeneratorBase::GetErrorValue(const BaseType& type) {
   if (type.IsUserDefinedType() ||
       type.ToString() == "list" ||
@@ -318,7 +448,7 @@ std::string CGeneratorBase::GetErrorValue(const BaseType& type) {
       type.ToString() == "bundle" ||
       type.ToString() == "string"||
       type.ToString() == "file")
-    return "NULL";
+    return "nullptr";
   if (type.ToString() == "bool")
     return "false";
   if (type.ToString() == "char")
@@ -326,31 +456,18 @@ std::string CGeneratorBase::GetErrorValue(const BaseType& type) {
   return "-1";
 }
 
-std::string CGeneratorBase::GetStringFromElementType(const BaseType& type) {
-  if (type.IsUserDefinedType())
-    return GetHandlePrefix() + type.ToString() + "_h ";
-  if (type.ToString() == "array")
-    return GetReturnTypeString(*type.GetMetaType()) + "*";
-
-  return type_map_[type.ToString()];
-}
-
-std::string CGeneratorBase::GetStructIdWithNamespace(const Structure& st) {
+std::string CGeneratorBase::GetHandlePrefix() {
+  std::string prefix =
+      IsProxy() ? PREFIX_RPC_PORT_PROXY : PREFIX_RPC_PORT_STUB;
   if (!HasNamespace())
-    return st.GetID();
-  return GetFileNamespace() + "_" + st.GetID();
-}
+    return prefix;
 
-std::string CGeneratorBase::GetInterfaceIdWithNamespace(const Interface& inf) {
-  if (!HasNamespace())
-    return inf.GetID();
-  return GetFileNamespace() + "_" + inf.GetID();
+  return prefix + "_" + GetFileNamespace() + "_";
 }
 
-std::string CGeneratorBase::GetHandlePrefix() {
-  if (!HasNamespace())
-    return "rpc_port_";
-  return "rpc_port_" + GetFileNamespace() + "_";
+const std::map<std::string, std::unique_ptr<Structure>>&
+CGeneratorBase::GetStructures() {
+  return structures_;
 }
 
 }  // namespace tidl
index caec145..651892e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
@@ -17,9 +17,9 @@
 #ifndef IDLC_C_GEN_C_GEN_BASE_H_
 #define IDLC_C_GEN_C_GEN_BASE_H_
 
+#include <map>
 #include <memory>
 #include <string>
-#include <map>
 
 #include "idlc/ast/type.h"
 #include "idlc/ast/structure.h"
@@ -32,34 +32,38 @@ class CGeneratorBase : public Generator {
   explicit CGeneratorBase(std::shared_ptr<Document> doc);
   virtual ~CGeneratorBase() = default;
 
-  std::string Trim(const std::string& str);
+  std::string RemoveLine(std::string lines, unsigned int line_num = 1);
   std::string SmartIndent(std::string lines);
-  std::string Tab(int cnt);
   std::string NLine(int cnt);
-  std::string ConvertTypeToString(ParameterType::Direction direction,
-                                  const BaseType& type, bool bconst = true);
+
   std::string GetFullNameFromType(const BaseType& type);
-  std::string GetParcelParamTypeString(const BaseType& type,
-                                       bool is_pointer = true);
+  std::string GetFullNameFromType(const BaseType& type, const Interface& inf);
+
+  std::string GetDataTypeString(const BaseType& type, bool is_pointer = true);
   std::string GetReturnTypeString(const BaseType& type);
   std::string GetParamTypeString(ParameterType::Direction direction,
-                                 const BaseType& type);
-  std::string GetStringFromElementType(const BaseType& type);
+      const BaseType& type);
+  std::string GetParamTypeString(ParameterType::Direction direction,
+      const BaseType& type, const Interface& inf);
+  std::string GetArgTypeString(const BaseType& type, const Interface& inf);
   std::string GetErrorValue(const BaseType& type);
+
   void AddStructureFromType(const BaseType& type);
-  const std::map<std::string, std::unique_ptr<Structure>>& GetStructures(void) {
-    return structures_;
-  }
+  void AddStructureFromType(const BaseType& type, const Interface& inf);
+
+  const std::map<std::string, std::unique_ptr<Structure>>& GetStructures();
 
   void GenVersion(std::ofstream& stream);
   void GenIncludeDefaultHeaders(std::ofstream& stream, bool body = true);
   void GenGNUSourceDefinition(std::ofstream& stream);
-  std::string GetStructIdWithNamespace(const Structure& st);
-  std::string GetInterfaceIdWithNamespace(const Interface& inf);
   std::string GetHandlePrefix();
+  std::string RemoveLastSpaces(const std::string& str);
 
  private:
-  bool StructureExist(const Structure& st);
+  std::string Tab(int cnt);
+  std::string Trim(const std::string& str);
+  std::string RemoveSpaces(const std::string& str);
+  bool StructureExist(const Structure* st);
 
  private:
   std::map<std::string, std::unique_ptr<Structure>> structures_;
index f258cb6..1ae1ddb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_GEN_BASE_CB_H_
 #define IDLC_C_GEN_C_GEN_BASE_CB_H_
 
-const char CB_VERSION[] =
+/**
+ * <VERSION> Version of TIDL Compiler.
+ */
+constexpr const char CB_VERSION[] =
 R"__c_cb(/*
- * Generated by tidlc $$.
+ * Generated by tidlc <VERSION>.
  */
 )__c_cb";
 
-const char CB_GNU_SOURCE[] =
+constexpr const char CB_GNU_SOURCE[] =
 R"__c_cb(
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 #endif
 )__c_cb";
 
-const char CB_HEADER[] =
+constexpr const char CB_HEADER[] =
 R"__c_cb(
 #include <stdbool.h>
 #include <bundle.h>
+#include <rpc-port.h>
 )__c_cb";
 
-const char CB_BODY_HEADER[] =
+constexpr const char CB_BODY_HEADER[] =
 R"__c_cb(
 #include <pthread.h>
 #include <stdio.h>
index f402fe0..4d09a80 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 - 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.
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <string.h>
+
 #include <vector>
 
 #include "idlc/gen/c_header_gen_base.h"
@@ -25,7 +27,28 @@ namespace {
 namespace tidl {
 
 CHeaderGeneratorBase::CHeaderGeneratorBase(std::shared_ptr<Document> doc)
-    : CGeneratorBase(doc) {}
+    : CGeneratorBase(doc) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() == Block::TYPE_STRUCTURE) {
+      auto& st = static_cast<const Structure&>(*b);
+      for (auto& e : st.GetElements().GetElms()) {
+        auto& type = e->GetType();
+        AddStructureFromType(type);
+      }
+    } else {
+      auto& inf = static_cast<const Interface&>(*b);
+      for (auto& d : inf.GetDeclarations().GetDecls()) {
+        for (auto& p : d->GetParameters().GetParams()) {
+          auto& type = p->GetParameterType().GetBaseType();
+          if (IsDelegateType(inf, type))
+            continue;
+
+          AddStructureFromType(type, inf);
+        }
+      }
+    }
+  }
+}
 
 void CHeaderGeneratorBase::GenPragmaOnce(std::ofstream& stream) {
   const char format[] = "#pragma once\n";
@@ -42,249 +65,106 @@ void CHeaderGeneratorBase::GenExplicitLinkageClose(std::ofstream& stream) {
   stream << CB_EXPLICIT_LINKAGE_CLOSE;
 }
 
-void CHeaderGeneratorBase::GenStructures(std::ofstream& stream) {
-  for (auto& i : GetDocument().GetBlocks()) {
-    if (i->GetType() == Block::TYPE_STRUCTURE) {
-      const Structure &st = static_cast<const Structure&>(*i);
-      GenStructure(stream, st);
-      for (auto& j : st.GetElements().GetElms()) {
-       auto& t = j->GetType();
-       AddStructureFromType(t);
-      }
-    } else {
-      const Interface &inf = static_cast<const Interface&>(*i);
-      for (auto& d : inf.GetDeclarations().GetDecls()) {
-        for (auto& p : d->GetParameters().GetParams()) {
-          if (IsDelegateType(inf, p->GetParameterType().GetBaseType()))
-            continue;
-          AddStructureFromType(p->GetParameterType().GetBaseType());
-        }
-      }
+void CHeaderGeneratorBase::GenStructureHandles(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() == Block::TYPE_STRUCTURE) {
+      auto& st = static_cast<const Structure&>(*b);
+      GenStructureHandle(stream, st);
     }
   }
 
-  for (auto& p : GetStructures()) {
-    const Structure& st = *p.second;
-    GenStructure(stream, st);
+  for (auto& i : GetStructures()) {
+    auto& st = i.second;
+    GenStructureHandle(stream, *st);
   }
 }
 
-void CHeaderGeneratorBase::GenStructure(std::ofstream& stream,
-                                        const Structure& st) {
-  GenStructureDeclaration(stream, st);
-  GenStructureConstructor(stream, st);
-  GenStructureDestructor(stream, st);
-  GenStructureCloner(stream, st);
-  GenStructureSetter(stream, st);
-  GenStructureGetter(stream, st);
-  GenStructureIterator(stream, st);
-  GenStructureRemover(stream, st);
-  GenStructureLengthGetter(stream, st);
-}
-
-void CHeaderGeneratorBase::GenStructureDeclaration(std::ofstream& stream,
-                                                   const Structure& st) {
-  GenTemplate(CB_STRUCT_DECL, stream,
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      },
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      });
-}
-
-void CHeaderGeneratorBase::GenStructureConstructor(std::ofstream& stream,
-                                                   const Structure& st) {
-  GenTemplate(CB_STRUCT_CTOR, stream,
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      },
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      });
-}
-
-void CHeaderGeneratorBase::GenStructureDestructor(std::ofstream& stream,
-                                                  const Structure& st) {
-  GenTemplate(CB_STRUCT_DTOR, stream,
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      },
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      });
-}
-
-void CHeaderGeneratorBase::GenStructureSetter(std::ofstream& stream,
-                                              const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    GenTemplate(CB_STRUCT_SETTER, stream,
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "list")
-              return "add";
-            return "set";
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetStructIdWithNamespace(st);
-          },
-          [&]()->std::string {
-            if (i->GetType().IsUserDefinedType())
-              return GetParcelParamTypeString(i->GetType());
-
-            if (i->GetType().ToString() == "list") {
-              if (i->GetType().GetMetaType()->IsUserDefinedType() ||
-                  i->GetType().GetMetaType()->ToString() == "list" ||
-                  i->GetType().GetMetaType()->ToString() == "array") {
-                return GetParcelParamTypeString(*i->GetType().GetMetaType());
-              } else {
-                return ConvertTypeToString(ParameterType::Direction::IN,
-                    *i->GetType().GetMetaType());
-              }
-            }
-
-            if (i->GetType().ToString() == "array") {
-              return GetStringFromElementType(i->GetType());
-            }
-
-            return ConvertTypeToString(ParameterType::Direction::IN,
-                i->GetType());
-          },
-          [&]()->std::string {
-            if (i->GetType().ToString() == "array") {
-              std::string str;
-              str += i->GetID();
-              str += ", ";
-              str += "int " + i->GetID() + "_size";
-              return str;
-            }
-            return i->GetID();
-          });
+void CHeaderGeneratorBase::GenStructures(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() == Block::TYPE_STRUCTURE) {
+      auto& st = static_cast<const Structure&>(*b);
+      GenStructure(stream, st);
+    }
   }
-}
 
-void CHeaderGeneratorBase::GenStructureGetter(std::ofstream& stream,
-                                              const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() == "list")
-      continue;
-
-    GenTemplate(CB_STRUCT_GETTER, stream,
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          return i->GetID();
-        },
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          if (i->GetType().ToString() == "array")
-              return GetStringFromElementType(i->GetType()) + "*";
-
-          return ConvertTypeToString(ParameterType::Direction::OUT,
-              i->GetType());
-        },
-        [&]()->std::string {
-          if (i->GetType().ToString() == "array") {
-            std::string str;
-            str += i->GetID();
-            str += ", ";
-            str += "int *" + i->GetID() + "_size";
-            return str;
-          }
-          return i->GetID();
-        });
+  for (auto& i : GetStructures()) {
+    auto& st = i.second;
+    GenStructure(stream, *st);
   }
 }
 
-void CHeaderGeneratorBase::GenStructureIterator(std::ofstream& stream,
-                                                const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() != "list")
-      continue;
+// @see #CB_STRUCTURE_HANDLE
+void CHeaderGeneratorBase::GenStructureHandle(std::ofstream& stream,
+    const Structure& st) {
+  std::string str = ReplaceAll(CB_STRUCTURE_HANDLE, "<PREFIX>",
+      GetHandlePrefix());
+  str = ReplaceAll(str, "<NAME>", st.GetID());
+  stream << SmartIndent(str);
+}
 
-    GenTemplate(CB_STRUCT_ITERATOR, stream,
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          return i->GetID();
-        },
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          if (i->GetType().GetMetaType()->IsUserDefinedType() ||
-              i->GetType().GetMetaType()->ToString() == "list" ||
-              i->GetType().GetMetaType()->ToString() == "array")
-            return GetParcelParamTypeString(*i->GetType().GetMetaType());
+// @see #CB_STRUCTURE_ARRAY_BASE
+void CHeaderGeneratorBase::GenStructureArrayBase(std::ofstream& stream,
+    const Structure& st) {
+  std::string str = ReplaceAll(CB_STRUCTURE_ARRAY_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  str = ReplaceAll(str, "<NAME>", st.GetID());
 
-          return ConvertTypeToString(ParameterType::Direction::IN,
-              *i->GetType().GetMetaType());
-        },
-        [&]()->std::string {
-          return i->GetID();
-        });
-  }
-}
+  auto& elm = st.GetElements().GetElms().front();
+  auto& type = elm->GetType();
+  auto param_type = GetParamTypeString(ParameterType::Direction::IN, type);
+  str = ReplaceAll(str, "<PARAM_TYPE_IN>", param_type);
 
-void CHeaderGeneratorBase::GenStructureRemover(std::ofstream& stream,
-                                               const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() != "list")
-      continue;
+  param_type = GetParamTypeString(ParameterType::Direction::OUT, type);
+  str = ReplaceAll(str, "<PARAM_TYPE_OUT>", param_type);
 
-    GenTemplate(CB_STRUCT_REMOVER, stream,
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          return i->GetID();
-        },
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        });
-  }
+  stream << SmartIndent(str);
 }
 
-void CHeaderGeneratorBase::GenStructureLengthGetter(std::ofstream& stream,
-                                                    const Structure& st) {
-  for (auto& i : st.GetElements().GetElms()) {
-    if (i->GetType().ToString() != "list")
-      continue;
+// @see #CB_STRUCTURE_LIST_BASE
+void CHeaderGeneratorBase::GenStructureListBase(std::ofstream& stream,
+    const Structure& st) {
+  std::string str = ReplaceAll(CB_STRUCTURE_LIST_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  str = ReplaceAll(str, "<NAME>", st.GetID());
+
+  auto& elm = st.GetElements().GetElms().front();
+  auto& type = elm->GetType();
+  auto param_type = GetParamTypeString(ParameterType::Direction::IN, type);
+  str = ReplaceAll(str, "<PARAM_TYPE_IN>", param_type);
+  stream << SmartIndent(str);
+}
 
-    GenTemplate(CB_STRUCT_LENGTH_GETTER, stream,
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        },
-        [&]()->std::string {
-          return i->GetID();
-        },
-        [&]()->std::string {
-          return GetStructIdWithNamespace(st);
-        });
+// @see #CB_STRUCTURE_BASE
+void CHeaderGeneratorBase::GenStructureBase(std::ofstream& stream,
+    const Structure& st) {
+  std::string str = ReplaceAll(CB_STRUCTURE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  str = ReplaceAll(str, "<NAME>", st.GetID());
+  stream << SmartIndent(str);
+
+  for (auto& e : st.GetElements().GetElms()) {
+    str = ReplaceAll(CB_STRUCTURE_BASE_SET_GET, "<PREFIX>", GetHandlePrefix());
+    str = ReplaceAll(str, "<NAME>", st.GetID());
+
+    auto& type = e->GetType();
+    auto param_type = GetParamTypeString(ParameterType::Direction::IN, type);
+    str = ReplaceAll(str, "<PARAM_TYPE_IN>", param_type);
+
+    param_type = GetParamTypeString(ParameterType::Direction::OUT, type);
+    str = ReplaceAll(str, "<PARAM_TYPE_OUT>", param_type);
+    str = ReplaceAll(str, "<ELEMENT_NAME>", e->GetID());
+    stream << SmartIndent(str);
   }
 }
 
-void CHeaderGeneratorBase::GenStructureCloner(std::ofstream& stream,
-                                              const Structure& st) {
-  GenTemplate(CB_STRUCT_CLONER, stream,
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      },
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      },
-      [&]()->std::string {
-        return GetStructIdWithNamespace(st);
-      });
+void CHeaderGeneratorBase::GenStructure(std::ofstream& stream,
+    const Structure& st) {
+  if (st.GetID().compare(0, strlen("array"), "array") == 0)
+    GenStructureArrayBase(stream, st);
+  else if (st.GetID().compare(0, strlen("list"), "list") == 0)
+    GenStructureListBase(stream, st);
+  else
+    GenStructureBase(stream, st);
 }
 
 }  // namespace tidl
index 4e2ad35..b61571c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 - 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.
@@ -33,21 +33,15 @@ class CHeaderGeneratorBase : public CGeneratorBase {
   void GenPragmaOnce(std::ofstream& stream);
   void GenExplicitLinkageOpen(std::ofstream& stream);
   void GenExplicitLinkageClose(std::ofstream& stream);
+  void GenStructureHandles(std::ofstream& stream);
   void GenStructures(std::ofstream& stream);
 
  private:
+  void GenStructureHandle(std::ofstream& stream, const Structure& st);
+  void GenStructureArrayBase(std::ofstream& stream, const Structure& st);
+  void GenStructureListBase(std::ofstream& stream, const Structure& st);
+  void GenStructureBase(std::ofstream& stream, const Structure& st);
   void GenStructure(std::ofstream& stream, const Structure& st);
-  void GenStructureDeclaration(std::ofstream& stream, const Structure& st);
-  void GenStructureParcelTo(std::ofstream& stream, const Structure& st);
-  void GenStructureParcelFrom(std::ofstream& stream, const Structure& st);
-  void GenStructureConstructor(std::ofstream& stream, const Structure& st);
-  void GenStructureDestructor(std::ofstream& stream, const Structure& st);
-  void GenStructureSetter(std::ofstream& stream, const Structure& st);
-  void GenStructureGetter(std::ofstream& stream, const Structure& st);
-  void GenStructureIterator(std::ofstream& stream, const Structure& st);
-  void GenStructureRemover(std::ofstream& stream, const Structure& st);
-  void GenStructureLengthGetter(std::ofstream& stream, const Structure& st);
-  void GenStructureCloner(std::ofstream& stream, const Structure& st);
 };
 
 }  // namespace tidl
index e0229f5..fe16760 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_HEADER_GEN_BASE_CB_H_
 #define IDLC_C_GEN_C_HEADER_GEN_BASE_CB_H_
 
-const char CB_EXPLICIT_LINKAGE_OPEN[] =
+constexpr const char CB_EXPLICIT_LINKAGE_OPEN[] =
 R"__c_cb(
 #ifdef __cplusplus
 extern "C" {
 #endif
 )__c_cb";
 
-const char CB_EXPLICIT_LINKAGE_CLOSE[] =
+constexpr const char CB_EXPLICIT_LINKAGE_CLOSE[] =
 R"__c_cb(
 #ifdef __cplusplus
 }
 #endif
 )__c_cb";
 
-const char CB_STRUCT_DECL[] =
-R"__c_cb(
-typedef struct $$_s *rpc_port_$$_h;
-)__c_cb";
 
-const char CB_STRUCT_CTOR[] =
+/**
+ * <PREFIX> The prefix of the handle.
+ * <NAME> The name of the handle.
+ */
+constexpr const char CB_STRUCTURE_HANDLE[] =
 R"__c_cb(
-int rpc_port_$$_create(rpc_port_$$_h *h);
+/**
+ * @brief The <PREFIX>_<NAME> handle.
+ */
+typedef struct <PREFIX>_<NAME>_s *<PREFIX>_<NAME>_h;
 )__c_cb";
 
-const char CB_STRUCT_DTOR[] =
+/**
+ * <PREFIX> The prefix of the array structure.
+ * <NAME> The name of the array structure.
+ * <PARAM_TYPE_IN> The type of the input parameter.
+ * <PARAM_TYPE_OUT> The type of the output parameter.
+ */
+constexpr const char CB_STRUCTURE_ARRAY_BASE[] =
 R"__c_cb(
-int rpc_port_$$_destroy(rpc_port_$$_h h);
-)__c_cb";
+/**
+ * @briefs Creates a <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a h should be released using the <PREFIX>_<NAME>_destroy()
+ *          if it's no longer needed.
+ * @param[out] h The <PREFIX>_<NAME> handle that is newly created
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h);
 
-const char CB_STRUCT_SETTER[] =
-R"__c_cb(
-int rpc_port_$$_$$_$$(rpc_port_$$_h h, $$$$);
-)__c_cb";
+/**
+ * @brief Destroys the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_create()
+ */
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h);
 
-const char CB_STRUCT_GETTER[] =
-R"__c_cb(
-int rpc_port_$$_get_$$(rpc_port_$$_h h, $$$$);
-)__c_cb";
+/**
+ * @brief Creates and returns a copy of the given <PREFIX>_<NAME> handle.
+ *
+ * @remarks A new created <PREFIX>_<NAME> should be released using
+ *          the <PREFIX>_<NAME>_destroy() if it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] clone If successful, a new created <PREFIX>_<NAME> handle will be returned
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone);
 
-const char CB_STRUCT_ITERATOR[] =
-R"__c_cb(
-int rpc_port_$$_foreach_$$(rpc_port_$$_h h,
-        bool (*callback)($$$$, void *user_data), void *user_data);
+/**
+ * @brief Sets the value to the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The value is internally copied and stored.
+ *          You should release it if it's allocaed when it's no longer needed,
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] value The array value
+ * @param[in] size The size of the array
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_get()
+ */
+int <PREFIX>_<NAME>_set(<PREFIX>_<NAME>_h h, <PARAM_TYPE_IN>*value, int size);
+
+/**
+ * @brief Gets the value from the <PREFIX>_<NAME> handle.
+ *
+ * @remarks A new created value should be released if it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] value The array value
+ * @param[out] size The size of the array
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_set()
+ */
+int <PREFIX>_<NAME>_get(<PREFIX>_<NAME>_h h, <PARAM_TYPE_OUT>*value, int *size);
 )__c_cb";
 
-const char CB_STRUCT_REMOVER[] =
+/**
+ * <PREFIX> The prefix of the list structure.
+ * <NAME> The name of the list structure.
+ * <PARAM_TYPE_IN> The type of the input parameter.
+ */
+constexpr const char CB_STRUCTURE_LIST_BASE[] =
 R"__c_cb(
-int rpc_port_$$_remove_$$(rpc_port_$$_h h, unsigned int nth);
+/**
+ * @brief Called to retrieve the value contained in the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a value MUST NOT be released by the application.
+ * @param[in] value The value of the list
+ * @param[in] user_data The user data passed from the foreach function
+ * @return @c true to continue with the next iteration of the loop,
+ *         otherwise @c false to break out of the loop
+ * @see <PREFIX>_<NAME>_foreach()
+ */
+typedef bool (*<PREFIX>_<NAME>_cb)(<PARAM_TYPE_IN>value, void *user_data);
+
+/**
+ * @brief Creates a <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a h handle should be released using the <PREFIX>_<NAME>_destroy()
+ *          if it's no longer needed.
+ * @param[out] h The <PREFIX>_<NAME> handle that is newly created
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h);
+
+/**
+ * @brief Destroys the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_create()
+ */
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h);
+
+/**
+ * @brief Creates and returns a copy of the given <PREFIX>_<NAME> handle.
+ *
+ * @remarks A new created <PREFIX>_<NAME> should be released using
+ *          the <PREFIX>_<NAME>_destroy() if it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] clone If successful, a new created <PREFIX>_<NAME> handle will be returned
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone);
+
+/**
+ * @brief Adds the value to the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The value is internally copied and stored.
+ *          You should release it if it's allocaed when it's no longer needed,
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] value The value
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_remove()
+ */
+int <PREFIX>_<NAME>_add(<PREFIX>_<NAME>_h h, <PARAM_TYPE_IN>value);
+
+/**
+ * @brief Retrieves all values contained in the <PREFIX>_<NAME> handle.
+ * @details This function called <PREFIX>_<NAME>_cb once for each value contained in the <PREFIX>_<NAME> handle.
+ *          If the <PREFIX>_<NAME>_cb callback function returns @c false, the iteration will be finished.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] callback The iteration callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_cb()
+ */
+int <PREFIX>_<NAME>_foreach(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_cb callback, void *user_data);
+
+/**
+ * @brief Removes the element at the given position in the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] nth The position of the element
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_remove(<PREFIX>_<NAME>_h h, unsigned int nth);
+
+/**
+ * @brief Gets the number of elements in the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] length The number of elements
+ * @return @c on 0 success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_length(<PREFIX>_<NAME>_h h, unsigned int *length);
 )__c_cb";
 
-const char CB_STRUCT_LENGTH_GETTER[] =
+/**
+ * <PREFIX> The prefix of the structure. e.g. rpc_port_proxy_ or rpc_port_stub_
+ * <NAME> The name of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE[] =
 R"__c_cb(
-int rpc_port_$$_get_$$_length(rpc_port_$$_h h, unsigned int *length);
+/**
+ * @brief Creates a <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a h handle should be released using the <PREFIX>_<NAME>_destroy()
+ *          if it's no longer needed.
+ * @param[out] h The <PREFIX>_<NAME> handle that is newly created
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMTER Invaid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h);
+
+/**
+ * @brief Destroys the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_create()
+ */
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h);
+
+/**
+ * @brief Creates and returns a copy of the given <PREFIX>_<NAME> handle.
+ *
+ * @remarks A new created <PREFIX>_<NAME> should be released using
+ *          the <PREFIX>_<NAME>_destroy() if it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] clone If successful, a new created <PREFIX>_<NAME> handle will be returned
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone);
 )__c_cb";
 
-const char CB_STRUCT_CLONER[] =
+/**
+ * <PREFIX> The prefix of the structure. e.g. rpc_port_proxy_ or rpc_port_stub_
+ * <NAME> The name of the structure.
+ * <PARAM_TYPE_IN> The type of the input parameter.
+ * <PARAM_TYPE_OUT> The type of the output parameter.
+ * <ELEMENT_NAME> The name of the element of the structure.
+ */
+constexpr const char CB_STRUCTURE_BASE_SET_GET[] =
 R"__c_cb(
-int rpc_port_$$_clone(rpc_port_$$_h h, rpc_port_$$_h *clone);
+/**
+ * @brief Sets the <ELEMENT_NAME> to the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The <ELEMENT_NAME> is internally copied and stored.
+ *          You should release it if it's allocated when it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] value The <ELEMENT_NAME>
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_get_<ELEMENT_NAME>()
+ */
+int <PREFIX>_<NAME>_set_<ELEMENT_NAME>(<PREFIX>_<NAME>_h h, <PARAM_TYPE_IN>value);
+
+/**
+ * @brief Gets the <ELEMENT_NAME> from the <PREFIX>_<NAME> handle.
+ *
+ * @remarks A new created value should be released if it's allocated when it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] value The <ELEMENT_NAME>
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_set_<ELEMENT_NAME>
+ */
+int <PREFIX>_<NAME>_get_<ELEMENT_NAME>(<PREFIX>_<NAME>_h h, <PARAM_TYPE_OUT>value);
 )__c_cb";
 
 #endif  // IDLC_C_GEN_C_HEADER_GEN_BASE_CB_H_
index 7c775f5..a6d46a5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
  * limitations under the License.
  */
 
-#include "idlc/gen/c_proxy_body_gen.h"
+#include <algorithm>
 
-namespace {
+#include "idlc/gen/c_proxy_body_gen.h"
 #include "idlc/gen/c_proxy_body_gen_cb.h"
-}
 
 namespace tidl {
 
-CProxyBodyGen::CProxyBodyGen(std::shared_ptr<Document> doc)
-    : CBodyGeneratorBase(doc) {}
+CProxyBodyGen::CProxyBodyGen(std::shared_ptr<Document> doc,
+    std::shared_ptr<Options> options)
+    : CBodyGeneratorBase(doc), options_(std::move(options)) {
+}
 
 void CProxyBodyGen::OnInitGen(std::ofstream& stream) {
   GenVersion(stream);
@@ -32,7 +33,11 @@ void CProxyBodyGen::OnInitGen(std::ofstream& stream) {
   GenIncludeHeader(stream);
   GenLogTag(stream, std::string("RPC_PORT_PROXY"));
   GenLogDefinition(stream);
-  GenTypedefProxyDelegate(stream);
+  GenBaseDefinition(stream);
+  GenInterfaceDelegateCallback(stream);
+  GenStructureDefs(stream);
+  GenInterfaceDefs(stream);
+  GenPrivateSharingListSet(stream);
   GenStructures(stream);
   GenInterfaces(stream);
 }
@@ -40,558 +45,555 @@ void CProxyBodyGen::OnInitGen(std::ofstream& stream) {
 void CProxyBodyGen::OnFiniGen(std::ofstream& stream) {
 }
 
-void CProxyBodyGen::GenTypedefProxyDelegate(std::ofstream& stream) {
-  const char format[] =
-      "typedef void (*proxy_delegate)(GList **list, rpc_port_parcel_h parcel," \
-      " int seq_id, int id);\n";
-  stream << NLine(1);
-  stream << std::string(format);
+// @see #CB_INTERFACE_DELEGATE_CALLBACK
+void CProxyBodyGen::GenInterfaceDelegateCallback(std::ofstream& stream) {
+  stream << SmartIndent(CB_INTERFACE_DELEGATE_CALLBACK);
 }
 
-void CProxyBodyGen::GenInterfaces(std::ofstream& stream) {
+void CProxyBodyGen::GenInterfaceDefs(std::ofstream& stream) {
   for (auto& i : GetDocument().GetBlocks()) {
     if (i->GetType() != Block::TYPE_INTERFACE)
       continue;
 
     const Interface &inf = static_cast<const Interface&>(*i);
-    GenInterface(stream, inf);
+    GenInterfaceDef(stream, inf);
   }
 }
 
-void CProxyBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) {
-  GenInterfaceFileSharing(stream, inf);
-  GenInterfaceEnumerations(stream, inf);
-  GenInterfaceDeclaration(stream, inf);
-  GenInterfaceDelegators(stream, inf);
-  GenInterfaceDelegatorTable(stream, inf);
-  GenInterfaceDelegatorHandler(stream, inf);
-  GenInterfaceConsumeCommand(stream, inf);
-  GenInterfaceOnConnectedEventCB(stream, inf);
-  GenInterfaceOnDisconnectedEventCB(stream, inf);
-  GenInterfaceOnRejectedEventCB(stream, inf);
-  GenInterfaceOnReceivedEventCB(stream, inf);
-  GenInterfaceMethods(stream, inf);
-  GenInterfaceHandleCtor(stream, inf);
-  GenInterfaceHandleDtor(stream, inf);
-  GenInterfaceCtor(stream, inf);
-  GenInterfaceConnect(stream, inf);
-  GenInterfaceDtor(stream, inf);
-  GenInterfaceConnectSync(stream, inf);
-}
+void CProxyBodyGen::GenInterfaceDef(std::ofstream& stream,
+    const Interface& inf) {
+   for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
 
-void CProxyBodyGen::GenInterfaceFileSharing(std::ofstream& stream,
-                                            const Interface& inf) {
-
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    for (auto& p : i->GetParameters().GetParams()) {
-      if ((p->GetParameterType().GetBaseType().ToString() == "list" ||
-          p->GetParameterType().GetBaseType().ToString() == "array") &&
-          p->GetParameterType().GetBaseType().GetMetaType()->ToString() == "file") {
-        if (p->GetParameterType().GetBaseType().ToString() == "array") {
-          stream << SmartIndent(std::string(CB_FILE_ARRAY_SHARING));
-        } else {
-          stream << SmartIndent(std::string(CB_FILE_LIST_SHARING));
-        }
-      }
-    }
+    GenInterfaceDelegateDef(stream, inf, *d);
   }
+
+   GenInterfaceBaseDef(stream, inf);
 }
 
+// @see #CB_INTERFACE_DELEGATE_DEF
+void CProxyBodyGen::GenInterfaceDelegateDef(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
 
-void CProxyBodyGen::GenInterfaceDeclaration(std::ofstream& stream,
-                                            const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_STRUCT, "##",
-      GetInterfaceIdWithNamespace(inf)));
+  stream << SmartIndent(code);
 }
 
-void CProxyBodyGen::GenInterfaceDelegators(std::ofstream& stream,
-                                           const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
-      continue;
-    GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i);
-  }
-}
+// @see #CB_INTERFACE_BASE_DEF
+void CProxyBodyGen::GenInterfaceBaseDef(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
 
-void CProxyBodyGen::GenInterfaceDelegator(std::ofstream& stream,
-                                          const std::string& id,
-                                          const Declaration& decl) {
-  GenInterfaceDelegatorDeclaration(stream, id, decl);
-  GenInterfaceDelegatorSerializer(stream, id, decl);
-  GenInterfaceDelegatorDeserializer(stream, id, decl);
-  GenInterfaceDelegatorConstructor(stream, id, decl);
-  GenInterfaceDelegatorDestructor(stream, id, decl);
-  GenInterfaceDelegatorDisposer(stream, id, decl);
-  GenInterfaceDelegatorInvoker(stream, id, decl);
+  stream << SmartIndent(code);
 }
 
-void CProxyBodyGen::GenInterfaceDelegatorDeclaration(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << SmartIndent(ReplaceAll(
-      CB_DELEGATE_STRUCT, "##", id + "_" + decl.GetID()));
-}
+void CProxyBodyGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
 
-void CProxyBodyGen::GenInterfaceDelegatorSerializer(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << SmartIndent(
-      ReplaceAll(CB_DELEGATE_SERIALIZER, "##", id + "_" + decl.GetID()));
+    const Interface &inf = static_cast<const Interface&>(*i);
+    GenInterface(stream, inf);
+  }
 }
 
-void CProxyBodyGen::GenInterfaceDelegatorDeserializer(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << SmartIndent(
-      ReplaceAll(CB_DELEGATE_DESERIALIZER, "##", id + "_" + decl.GetID()));
-}
+void CProxyBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) {
+  GenInterfaceDelegateEnumBase(stream, inf);
 
-void CProxyBodyGen::GenInterfaceDelegatorConstructor(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_DELEGATE_CTOR, "##", id + "_" + decl.GetID()),
-        [&]()->std::string {
-          return id;
-        },
-        [&]()->std::string {
-          return decl.GetID();
-        }));
-}
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
 
-void CProxyBodyGen::GenInterfaceDelegatorDisposer(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_DELEGATE_DISPOSER, "##", id + "_" + decl.GetID()),
-        [&]()->std::string {
-          return id;
-        }));
-}
+    GenInterfaceDelegateBase(stream, inf, *d);
+  }
 
-void CProxyBodyGen::GenInterfaceDelegatorInvoker(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  const char parcel[] = "$$(parcel, $$);\n";
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_DELEGATE_INVOKER, "##", id + "_" + decl.GetID()),
-        [&]()->std::string {
-          return id;
-        },
-        [&]()->std::string {
-          return decl.GetID();
-        },
-        [&]()->std::string {
-          std::string str;
-          int cnt = 0;
-          for (auto& i : decl.GetParameters().GetParams()) {
-            str += GetParcelParamTypeString(
-              i->GetParameterType().GetBaseType(), false) + i->GetID();
-            str += " = " + GetErrorValue(i->GetParameterType().GetBaseType());
-            str += ";" + NLine(1);
-            cnt++;
-          }
-          if (cnt > 0)
-            str += NLine(1);
-          for (auto& i : decl.GetParameters().GetParams()) {
-            if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
-                i->GetParameterType().GetBaseType().ToString() == "list" ||
-                i->GetParameterType().GetBaseType().ToString() == "array") {
-              str += GetConstructorString(i->GetParameterType().GetBaseType(),
-                  i->GetID());
-            }
-            str += GenTemplateString(parcel,
-                [&]()->std::string {
-                    return GetParcelReadFunctionString(
-                        i->GetParameterType().GetBaseType(), true);
-                },
-                [&]()->std::string {
-                  if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
-                      i->GetParameterType().GetBaseType()
-                          .ToString() == "list" ||
-                      i->GetParameterType().GetBaseType().ToString() == "array")
-                    return "&" + i->GetID() + "->parcelable, " + i->GetID();
-                  return "&" + i->GetID();
-                });
-          }
-          return str;
-        },
-        [&]()->std::string {
-          std::string str;
-          str += "handle->callback(handle->user_data";
-          for (auto& i : decl.GetParameters().GetParams()) {
-            str += ", ";
-            str += i->GetID();
-          }
-          str += ");" + NLine(1);
-          return str;
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : decl.GetParameters().GetParams()) {
-            str += GetDestructorString(i->GetParameterType().GetBaseType(),
-                i->GetID());
-            str += NLine(1);
-          }
-          return str;
-        }));
-}
+  GenInterfaceDelegateTable(stream, inf);
+  GenInterfaceMethodEnumBase(stream, inf);
+  GenInterfaceBase(stream, inf);
 
-void CProxyBodyGen::GenInterfaceDelegatorDestructor(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << SmartIndent(ReplaceAll(
-      CB_DELEGATE_DTOR, "##", id + "_" + decl.GetID()));
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenInterfaceMethodBase(stream, inf, *d);
+  }
 }
 
-void CProxyBodyGen::GenInterfaceDelegatorTable(std::ofstream& stream,
-                                               const Interface& inf) {
-  const char block[] =
-      "static proxy_delegate __$$_delegate_table[] = {\n" \
-      "$$" \
-      "};\n";
-  const char delegate_format[] = "[$$] = $$,\n";
-  std::string str;
-  int cnt = 0;
-
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+// @see #CB_INTERFACE_BASE
+void CProxyBodyGen::GenInterfaceBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string prefix = GetHandlePrefix();
+  std::string code = ReplaceAll(CB_INTERFACE_BASE, "<PREFIX>", prefix);
+  std::string name = inf.GetID();
+  code = ReplaceAll(code, "<NAME>", name);
+  std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_PREFIX>", prefix);
+  std::transform(name.begin(), name.end(), name.begin(), ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_NAME>", name);
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_DELEGATE_ENUM_BASE
+void CProxyBodyGen::GenInterfaceDelegateEnumBase(std::ofstream& stream,
+    const Interface& inf) {
+  unsigned int num = 1;
+  std::string enums;
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
       continue;
-    str += GenTemplateString(delegate_format,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf) + "_DELEGATE_" + i->GetID();
-        },
-        [&]()->std::string {
-          return "__" + GetInterfaceIdWithNamespace(inf) + "_delegate_"
-              + i->GetID();
-        });
-    cnt++;
+
+    enums += GetHandlePrefix() + "_" + inf.GetID() + "_DELEGATE_" + d->GetID();
+    enums += " = " + std::to_string(num++) + ",";
+    enums += NLine(1);
   }
 
-  if (cnt == 0)
+  if (enums.empty())
     return;
 
-  stream << NLine(1);
-  stream << SmartIndent(GenTemplateString(block,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          return str;
-        }));
-}
+  std::transform(enums.begin(), enums.end(), enums.begin(), ::toupper);
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_ENUM_BASE, "<ENUMS>",
+      enums);
+  code = ReplaceAll(code, "<PREFIX>", GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
 
-void CProxyBodyGen::GenInterfaceDelegatorHandler(std::ofstream& stream,
-                                                 const Interface& inf) {
-  std::string str;
-  int cnt = 0;
+  stream << SmartIndent(code);
+}
 
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
-      continue;
-    cnt++;
+std::string CProxyBodyGen::GenDelegateArgsDecl(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    code += GetArgTypeString(type, inf) + p->GetID() + " = " +
+        GetErrorValue(param_type.GetBaseType()) + ";" + NLine(1);
   }
 
-  stream << SmartIndent(GenTemplateString(
-      ReplaceAll(CB_PROCESS_RECEIVED_EVENT, "##",
-          GetInterfaceIdWithNamespace(inf)),
-          [&]()->std::string {
-            if (cnt == 0)
-              return str;
-            return ReplaceAll(CB_PROCESS_RECEIVED_EVENT_IMPL, "##",
-                GetInterfaceIdWithNamespace(inf));
-          }));
+  return code;
 }
 
-void CProxyBodyGen::GenInterfaceConsumeCommand(std::ofstream& stream,
-                                               const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_CONSUME_COMMAND, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
+// @see #CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_READ
+// @see #CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_READ
+// @see #CB_INTERFACE_DELEGATE_STRING_PARCEL_READ
+// @see #CB_INTERFACE_DELEGATE_BASE_PARCEL_READ
+std::string CProxyBodyGen::GenDelegateParcelRead(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    std::string param_read_code;
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      param_read_code = ReplaceAll(
+          CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_READ, "<PREFIX>",
+          GetHandlePrefix());
+
+      std::string name = GetFullNameFromType(type, inf);
+      param_read_code = ReplaceAll(param_read_code, "<NAME>", name);
+      param_read_code = ReplaceAll(param_read_code, "<ARG>", p->GetID());
+    } else if (type.ToString() == "bundle") {
+      param_read_code = ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_READ,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      param_read_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_PARCEL_READ,
+          "<ARG>", p->GetID());
+    } else {
+      param_read_code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE_PARCEL_READ,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      param_read_code = ReplaceAll(param_read_code, "<ARG>", p->GetID());
+    }
 
-void CProxyBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream,
-                                                   const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_ON_CONNECTED, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
+    code += param_read_code;
+  }
 
-void CProxyBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
-                                                      const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_ON_DISCONNECTED, "##",
-      GetInterfaceIdWithNamespace(inf)));
+  return RemoveLine(code);
 }
 
-void CProxyBodyGen::GenInterfaceOnRejectedEventCB(std::ofstream& stream,
-                                                  const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_ON_REJECTED, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
+// @see CB_INTERFACE_DELEGATE_USER_DEFINED_ARG_FREE
+// @see CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE
+// @see CB_INTERFACE_DELEGATE_STRING_ARG_FREE
+std::string CProxyBodyGen::GenDelegateArgsFree(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    std::string param_free_code;
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      param_free_code = ReplaceAll(
+          CB_INTERFACE_DELEGATE_USER_DEFINED_ARG_FREE, "<PREFIX>",
+          GetHandlePrefix());
+
+      std::string name = GetFullNameFromType(type, inf);
+      param_free_code = ReplaceAll(param_free_code, "<NAME>", name);
+      param_free_code = ReplaceAll(param_free_code, "<ARG>", p->GetID());
+    } else if (type.ToString() == "bundle") {
+      param_free_code = ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      param_free_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_ARG_FREE,
+          "<ARG>", p->GetID());
+    }
 
-void CProxyBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream,
-                                                  const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_ON_RECEIVED, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
+    code += param_free_code;
+  }
 
-void CProxyBodyGen::GenInterfaceMethods(std::ofstream& stream,
-                                        const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+  return RemoveLine(code);
+}
+
+std::string CProxyBodyGen::GenDelegateCallbackArgs(const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams())
+    code += ", " + p->GetID();
+
+  return code;
+}
+
+// @see CB_INTERFACE_DELEGATE_BASE
+void CProxyBodyGen::GenInterfaceDelegateBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+
+  std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() +
+      "_DELEGATE_" + decl.GetID();
+  std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(),
+      ::toupper);
+  code = ReplaceAll(code, "<DELEGATE_ENUM_VALUE>", enum_value);
+  code = ReplaceAll(code, "<DELEGATE_ARGS_DECL>",
+      GenDelegateArgsDecl(inf, decl));
+  code = ReplaceAll(code, "<DELEGATE_PARCEL_READ>",
+      GenDelegateParcelRead(inf, decl));
+  code = ReplaceAll(code, "<DELEGATE_ARGS_FREE>",
+      GenDelegateArgsFree(inf, decl));
+  code = ReplaceAll(code, "<DELEGATE_CALLBACK_ARGS>",
+      GenDelegateCallbackArgs(decl));
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_DELEGATE_TABLE
+// @see #CB_INTERFACE_DELEGATE_TABLE_MEMBER
+void CProxyBodyGen::GenInterfaceDelegateTable(std::ofstream& stream,
+    const Interface& inf) {
+  std::string delegate_handlers;
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
       continue;
 
-    stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_INTERFACE_METHODS, "##",
-          GetInterfaceIdWithNamespace(inf)),
-          [&]()->std::string {
-            return GetReturnTypeString(i->GetType());
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            std::string str;
-            for (auto& p : i->GetParameters().GetParams()) {
-              str += ", ";
-              if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) {
-                str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" +
-                    p->GetParameterType().GetBaseType().ToString() +
-                    "_h " + p->GetID();
-              } else {
-                str += GetParamTypeString(p->GetParameterType().GetDirection(),
-                    p->GetParameterType().GetBaseType()) + p->GetID();
-              }
-            }
-            return str;
-          },
-          [&]()->std::string {
-            if (GetReturnTypeString(i->GetType()) != "void ")
-              return GetReturnTypeString(i->GetType()) + "ret = " +
-                  GetErrorValue(i->GetType()) + ";";
-            return "";
-          },
-          [&]()->std::string {
-            std::string str;
-            for (auto& p : i->GetParameters().GetParams()) {
-              if (p->GetParameterType().GetDirection() ==
-                  ParameterType::Direction::OUT ||
-                  p->GetParameterType().GetBaseType().IsUserDefinedType() ||
-                  p->GetParameterType().GetBaseType().ToString() == "list" ||
-                  p->GetParameterType().GetBaseType().ToString() == "array" ||
-                  p->GetParameterType().GetBaseType().ToString() == "bundle")
-                str += " || !" + p->GetID();
-            }
-            return str;
-          },
-          [&]()->std::string {
-            if (GetReturnTypeString(i->GetType()) != "void ")
-              return " ret";
-            return "";
-          },
-          [&]()->std::string {
-            if (GetReturnTypeString(i->GetType()) != "void ")
-              return " ret";
-            return "";
-          },
-          [&]()->std::string {
-            for (auto& p : i->GetParameters().GetParams()) {
-              if (p->GetParameterType().GetDirection() ==
-                  ParameterType::Direction::IN &&
-                  p->GetParameterType().GetBaseType().ToString() == "file") {
-                return ReplaceAll(CB_PRIVATE_SHARING_BLOCK, "##",
-                            p->GetID());
-              }
-
-              if ((p->GetParameterType().GetBaseType().ToString() == "list" ||
-                  p->GetParameterType().GetBaseType().ToString() == "array") &&
-                  p->GetParameterType().GetBaseType().GetMetaType()->ToString() == "file") {
-                if (p->GetParameterType().GetBaseType().ToString() == "array") {
-
-                  return ReplaceAll(CB_ARRAY_PRIVATE_SHARING_BLOCK, "##",
-                            p->GetID());
-                } else {
-                  return ReplaceAll(CB_LIST_PRIVATE_SHARING_BLOCK, "##",
-                            p->GetID());
-                }
-              }
-            }
-            return "";
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetMethodWriteString(inf, *i);
-          },
-          [&]()->std::string {
-            return GetMethodReadString(inf, *i);
-          }));
+    std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() +
+        "_DELEGATE_" + d->GetID();
+    std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(),
+        ::toupper);
+    std::string member = ReplaceAll(CB_INTERFACE_DELEGATE_TABLE_MEMBER,
+        "<ENUM_VALUE>", enum_value);
+    member = ReplaceAll(member, "<PREFIX>", GetHandlePrefix());
+    member = ReplaceAll(member, "<NAME>", inf.GetID());
+    member = ReplaceAll(member, "<DELEGATE_NAME>", d->GetID());
+    member = RemoveLine(member);
+
+    delegate_handlers += member;
   }
-}
 
-void CProxyBodyGen::GenInterfaceHandleCtor(std::ofstream& stream,
-                                           const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_HANDLE_CTOR, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
+  if (delegate_handlers.empty())
+    return;
 
-void CProxyBodyGen::GenInterfaceHandleDtor(std::ofstream& stream,
-                                           const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_HANDLE_DTOR, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_TABLE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_HANDLERS>", delegate_handlers);
 
-void CProxyBodyGen::GenInterfaceCtor(std::ofstream& stream,
-                                        const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_CTOR, "##",
-      GetInterfaceIdWithNamespace(inf)));
+  stream << SmartIndent(code);
 }
 
-void CProxyBodyGen::GenInterfaceConnect(std::ofstream& stream,
-                                        const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_CONNECT, "##",
-      GetInterfaceIdWithNamespace(inf)));
+// @see #CB_INTERFACE_METHOD_ENUM_BASE
+void CProxyBodyGen::GenInterfaceMethodEnumBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string enums;
+  enums += GetHandlePrefix() + "_" + inf.GetID() + "_METHOD_RESULT_,";
+  enums += NLine(1);
+  enums += GetHandlePrefix() + "_" + inf.GetID() + "_METHOD_CALLBACK_,";
+  enums += NLine(1);
+
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() +
+        "_METHOD_" + d->GetID() + ",";
+    enums += enum_value;
+    enums += NLine(1);
+  }
+
+  std::transform(enums.begin(), enums.end(), enums.begin(), ::toupper);
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, "<ENUMS>",
+      enums);
+  code = ReplaceAll(code, "<PREFIX>", GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+
+  stream << SmartIndent(code);
 }
 
-void CProxyBodyGen::GenInterfaceDtor(std::ofstream& stream,
-                                           const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_DTOR, "##",
-      GetInterfaceIdWithNamespace(inf)));
+std::string CProxyBodyGen::GenMethodParams(const Interface& inf,
+    const Declaration& decl) {
+  std::string params;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, inf) +
+        p->GetID();
+  }
+
+  return params;
 }
 
-void CProxyBodyGen::GenInterfaceConnectSync(std::ofstream& stream,
-                                            const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_CONNECT_SYNC, "##",
-      GetInterfaceIdWithNamespace(inf)));
+std::string CProxyBodyGen::GenMethodParamsCheck(const Interface& inf,
+    const Declaration& decl) {
+  std::string params_check;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array" ||
+        type.ToString() == "bundle" ||
+        type.ToString() == "string" ||
+        type.ToString() == "file")
+      params_check += " || " + p->GetID() + " == nullptr";
+  }
+
+  return params_check;
 }
 
-std::string CProxyBodyGen::GetMethodWriteString(const Interface& inf,
-                                                const Declaration& decl) {
-  const char setter[] = "$$($$, $$);\n";
-  const char ternary_operation[] = "## ? ## : \"\"";
-  std::string str;
+// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_STRING_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_BASE_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_LIST_FILE_SET_PRIVATE_SHARING
+// @see #CB_INTERFACE_METHOD_ARRAY_FILE_SET_PRIVATE_SHARING
+// @see #CB_INTERFACE_METHOD_FILE_SET_PRIVATE_SHARING
+std::string CProxyBodyGen::GenMethodParcelWrite(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
   for (auto& p : decl.GetParameters().GetParams()) {
-    if (p->GetParameterType().GetDirection() == ParameterType::Direction::OUT)
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::IN)
       continue;
-    if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) {
-      str += GenTemplateString(ReplaceAll(CB_DELEGATE_BLOCK, "##",
-          GetInterfaceIdWithNamespace(inf) + "_" + p->GetParameterType()
-              .GetBaseType().ToString()),
-          [&]()->std::string {
-            return p->GetID();
-          });
+
+    std::string parcel_write_code;
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_write_code = ReplaceAll(
+          CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "<ARG>",
+          p->GetID());
+      std::string name = GetFullNameFromType(type, inf);
+      parcel_write_code += GetPrivateSharingString(type, inf, "h->port",
+          p->GetID());
+    } else if (type.ToString() == "bundle") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "file") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+      parcel_write_code += GetPrivateSharingString(type, inf, "h->port",
+          p->GetID());
     } else {
-      str += GenTemplateString(setter,
-          [&]()->std::string {
-            return GetParcelWriteFunctionString(
-                p->GetParameterType().GetBaseType(), true);
-          },
-          [&]()->std::string {
-            return "parcel";
-          },
-          [&]()->std::string {
-            if (p->GetParameterType().GetBaseType().IsUserDefinedType() ||
-                p->GetParameterType().GetBaseType().ToString() == "list" ||
-                p->GetParameterType().GetBaseType().ToString() == "array") {
-              if (p->GetParameterType().GetDirection()
-                  == ParameterType::Direction::REF)
-                return "&(*" + p->GetID() + ")->parcelable, " + "*"
-                    + p->GetID();
-              else
-                return "&" + p->GetID() + "->parcelable, " + p->GetID();
-            } else if (p->GetParameterType().GetDirection()
-                       == ParameterType::Direction::REF) {
-              if (p->GetParameterType().GetBaseType().ToString() == "string"
-                  || p->GetParameterType().GetBaseType().ToString() == "file")
-                return ReplaceAll(ternary_operation, "##", "*" + p->GetID());
-              return "*" + p->GetID();
-            } else if (p->GetParameterType().GetBaseType().ToString() == "string"
-                || p->GetParameterType().GetBaseType().ToString() == "file") {
-              return ReplaceAll(ternary_operation, "##", p->GetID());
-            }
-            return p->GetID();
-          });
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_write_code = ReplaceAll(parcel_write_code, "<ARG>",
+          p->GetID());
     }
+
+    code += parcel_write_code;
   }
-  return str;
+
+  return RemoveLine(code);
 }
 
-std::string CProxyBodyGen::GetMethodReadString(const Interface& inf,
-                                               const Declaration& decl) {
-  const char setter[] = "$$($$, $$);\n";
-  std::string str;
-  if (decl.GetMethodType() != Declaration::MethodType::SYNC) {
-    str += "set_last_result(r);" + NLine(1);
-    return str;
+// @see #CB_INTERFACE_METHOD_DELEGATE_APPEND
+std::string CProxyBodyGen::GenMethodDelegateAppend(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type)) {
+      std::string delegate_append_code = ReplaceAll(
+          CB_INTERFACE_METHOD_DELEGATE_APPEND, "<ARG>", p->GetID());
+      code += delegate_append_code;
+    }
   }
-  str += GenTemplateString(CB_RECEIVE_BLOCK,
-      [&]()->std::string {
-        std::string s;
-        for (auto& p : decl.GetParameters().GetParams()) {
-          if (p->GetParameterType().GetDirection() !=
-              ParameterType::Direction::OUT)
-            continue;
-          s += GetReturnTypeString(p->GetParameterType().GetBaseType()) +
-              "out_" + p->GetID() + ";" + NLine(1);
-        }
-        return s;
-      },
-      [&]()->std::string {
-        return GetInterfaceIdWithNamespace(inf);
-      },
-      [&]()->std::string {
-        std::string s;
-        for (auto& p : decl.GetParameters().GetParams()) {
-          if (p->GetParameterType().GetDirection() !=
-              ParameterType::Direction::OUT)
-            continue;
-          if (p->GetParameterType().GetBaseType().IsUserDefinedType() ||
-              p->GetParameterType().GetBaseType().ToString() == "list" ||
-              p->GetParameterType().GetBaseType().ToString() == "array") {
-            s += GetConstructorString(p->GetParameterType().GetBaseType(),
-                "out_" + p->GetID());
-            }
-            s += GenTemplateString(setter,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(
-                      p->GetParameterType().GetBaseType(), true);
-                },
-                [&]()->std::string {
-                  return "parcel_received";
-                },
-                [&]()->std::string {
-                  auto& t = p->GetParameterType().GetBaseType();
-                  if (t.IsUserDefinedType() || t.ToString() == "list" ||
-                      t.ToString() == "array") {
-                    return "&out_" + p->GetID() + "->parcelable, out_"
-                        + p->GetID();
-                  }
-
-                  return "&out_" + p->GetID();
-                });
-            s += "*" + p->GetID() + " = out_" + p->GetID() + ";" + NLine(1);
-          }
-          if (GetReturnTypeString(decl.GetType()) != "void ") {
-            if (decl.GetType().IsUserDefinedType() ||
-                decl.GetType().ToString() == "list" ||
-                decl.GetType().ToString() == "array") {
-              s += GetConstructorString(decl.GetType(), "ret");
-            }
-            s += GenTemplateString(setter,
-                [&]()->std::string {
-                  return GetParcelReadFunctionString(decl.GetType(), false);
-                },
-                [&]()->std::string {
-                  return "parcel_received";
-                },
-                [&]()->std::string {
-                  if (decl.GetType().IsUserDefinedType() ||
-                      decl.GetType().ToString() == "list" ||
-                      decl.GetType().ToString() == "array")
-                    return "&ret->parcelable, ret";
-                  return "&ret";
-                });
-          }
-          return s;
-        });
-  if (GetReturnTypeString(decl.GetType()) != "void ") {
-    str += "set_last_result(r);" + NLine(1);
-    str += NLine(1);
-    str += "return ret;";
+
+  return RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_METHOD_ASYNC_BASE
+std::string CProxyBodyGen::GenMethodAsyncBase(const Interface& inf,
+    const Declaration& decl) {
+  std::string prefix = GetHandlePrefix();
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_ASYNC_BASE, "<PREFIX>",
+      prefix);
+  std::string name = inf.GetID();
+  code = ReplaceAll(code, "<NAME>", name);
+  std::string method_name = decl.GetID();
+  code = ReplaceAll(code, "<METHOD_NAME>", method_name);
+  std::string args = GenMethodParams(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARAMS>", args);
+  std::string args_check = GenMethodParamsCheck(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARAMS_CHECK>", args_check);
+  std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_PREFIX>", prefix);
+  std::transform(name.begin(), name.end(), name.begin(), ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_NAME>", name);
+  std::transform(method_name.begin(), method_name.end(), method_name.begin(),
+      ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_METHOD_NAME>", method_name);
+  std::string parcel_write = GenMethodParcelWrite(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARCEL_WRITE>", parcel_write);
+  std::string delegate_append = GenMethodDelegateAppend(inf, decl);
+  code = ReplaceAll(code, "<METHOD_DELEGATE_APPEND>", delegate_append);
+  return code;
+}
+
+std::string CProxyBodyGen::GenMethodArgs(const Interface& inf,
+    const Declaration& decl) {
+  std::string args_code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::OUT)
+      continue;
+
+    auto& type = param_type.GetBaseType();
+    args_code += GetReturnTypeString(type) + "new_" + p->GetID() + ";";
+    args_code += NLine(1);
   }
-  return str;
+
+  return args_code;
+}
+
+// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_STRING_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_BASE_PARCEL_READ
+std::string CProxyBodyGen::GenMethodParcelReadBase(const Interface& inf,
+    const BaseType& type, const std::string& param_name) {
+  std::string parcel_read_code;
+  if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_read_code = ReplaceAll(
+          CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ, "<PREFIX>",
+          GetHandlePrefix());
+      std::string name = GetFullNameFromType(type, inf);
+      parcel_read_code = ReplaceAll(parcel_read_code, "<NAME>", name);
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ARG>", param_name);
+    } else if (type.ToString() == "bundle") {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ,
+          "<ARG>", param_name);
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ,
+          "<ARG>", param_name);
+    } else {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ARG>",
+          param_name);
+    }
+
+  return parcel_read_code;
+}
+
+// @see #CB_INTERFACE_METHOD_VALUE_SET
+std::string CProxyBodyGen::GenMethodParcelRead(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  std::string parcel_read_code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::OUT)
+      continue;
+
+    auto& type = param_type.GetBaseType();
+    code += GenMethodParcelReadBase(inf, type, "new_" + p->GetID());
+    code += ReplaceAll(CB_INTERFACE_METHOD_PARAM_SET, "<PARAM>",
+        p->GetID());
+  }
+
+  // Return Value
+  auto& base_type = decl.GetType();
+  code += GenMethodParcelReadBase(inf, base_type, "ret_");
+  return RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_METHOD_BASE
+std::string CProxyBodyGen::GenMethodBase(const Interface& inf,
+    const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_BASE, "<RETURN_TYPE>",
+      GetReturnTypeString(decl.GetType()));
+  std::string prefix = GetHandlePrefix();
+  code = ReplaceAll(code, "<PREFIX>", prefix);
+  std::string name = inf.GetID();
+  code = ReplaceAll(code, "<NAME>", name);
+  std::string method_name = decl.GetID();
+  code = ReplaceAll(code, "<METHOD_NAME>", method_name);
+  std::string args = GenMethodParams(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARAMS>", args);
+  std::string values = GenMethodArgs(inf, decl);
+  code = ReplaceAll(code, "<METHOD_ARGS>", values);
+  std::string error_value = GetErrorValue(decl.GetType());
+  code = ReplaceAll(code, "<ERROR_VALUE>", error_value);
+  std::string args_check = GenMethodParamsCheck(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARAMS_CHECK>", args_check);
+  std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_PREFIX>", prefix);
+  std::transform(name.begin(), name.end(), name.begin(), ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_NAME>", name);
+  std::transform(method_name.begin(), method_name.end(), method_name.begin(),
+      ::toupper);
+  code = ReplaceAll(code, "<UPPERCASE_METHOD_NAME>", method_name);
+  std::string parcel_write = GenMethodParcelWrite(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARCEL_WRITE>", parcel_write);
+  std::string parcel_read = GenMethodParcelRead(inf, decl);
+  code = ReplaceAll(code, "<METHOD_PARCEL_READ>", parcel_read);
+  std::string delegate_append = GenMethodDelegateAppend(inf, decl);
+  code = ReplaceAll(code, "<METHOD_DELEGATE_APPEND>", delegate_append);
+  return code;
+}
+
+void CProxyBodyGen::GenInterfaceMethodBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code;
+  auto method_type = decl.GetMethodType();
+  if (method_type == Declaration::MethodType::ASYNC)
+    code = GenMethodAsyncBase(inf, decl);
+  else
+    code = GenMethodBase(inf, decl);
+
+  stream << SmartIndent(code);
 }
 
 }  // namespace tidl
index a89c602..e523f24 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #include <string>
 
 #include "idlc/gen/c_body_gen_base.h"
+#include "idlc/options.h"
 
 namespace tidl {
 
 class CProxyBodyGen : public CBodyGeneratorBase {
  public:
-  explicit CProxyBodyGen(std::shared_ptr<Document> doc);
+  explicit CProxyBodyGen(std::shared_ptr<Document> doc,
+      std::shared_ptr<Options> options);
   virtual ~CProxyBodyGen() = default;
 
   void OnInitGen(std::ofstream& stream) override;
   void OnFiniGen(std::ofstream& stream) override;
 
  private:
-  void GenTypedefProxyDelegate(std::ofstream& stream);
-  void GenInterfaces(std::ofstream& stream);
+  void GenInterfaceDefs(std::ofstream& stream);
+  void GenInterfaceDef(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateDef(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+  void GenInterfaceBaseDef(std::ofstream& stream, const Interface& inf);
 
- private:
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterfaceDelegateCallback(std::ofstream& stream);
   void GenInterface(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceFileSharing(std::ofstream& stream, const Interface& st);
-  void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDelegatorTable(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDelegatorHandler(std::ofstream& stream,
-                                    const Interface& inf);
-  void GenInterfaceConsumeCommand(std::ofstream& stream,
-                                  const Interface& inf);
-  void GenInterfaceOnConnectedEventCB(std::ofstream& stream,
-                                      const Interface& inf);
-  void GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
-                                         const Interface& inf);
-  void GenInterfaceOnRejectedEventCB(std::ofstream& stream,
-                                     const Interface& inf);
-  void GenInterfaceOnReceivedEventCB(std::ofstream& stream,
-                                     const Interface& inf);
-  void GenInterfaceMethods(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceHandleCtor(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceHandleDtor(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceCtor(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceConnect(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDtor(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceConnectSync(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateEnumBase(std::ofstream& stream,
+      const Interface& inf);
+  void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+  void GenInterfaceDelegateTable(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethodEnumBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethodBase(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
 
- private:
-  void GenInterfaceDelegator(std::ofstream& stream, const std::string& id,
-                             const Declaration& decl);
-  void GenInterfaceDelegatorDeclaration(std::ofstream& stream,
-                                        const std::string& id,
-                                        const Declaration& decl);
-  void GenInterfaceDelegatorSerializer(std::ofstream& stream,
-                                       const std::string& id,
-                                       const Declaration& decl);
-  void GenInterfaceDelegatorDeserializer(std::ofstream& stream,
-                                         const std::string& id,
-                                         const Declaration& decl);
-  void GenInterfaceDelegatorConstructor(std::ofstream& stream,
-                                        const std::string& id,
-                                        const Declaration& decl);
-  void GenInterfaceDelegatorDisposer(std::ofstream& stream,
-                                     const std::string& id,
-                                     const Declaration& decl);
-  void GenInterfaceDelegatorInvoker(std::ofstream& stream,
-                                    const std::string& id,
-                                    const Declaration& decl);
-  void GenInterfaceDelegatorDestructor(std::ofstream& stream,
-                                       const std::string& id,
-                                       const Declaration& decl);
+  bool HasListFile(const Interface& inf);
 
- private:
-  std::string GetMethodWriteString(const Interface& inf,
-                                   const Declaration& decl);
-  std::string GetMethodReadString(const Interface& inf,
-                                  const Declaration& decl);
+  std::string GenDelegateArgsDecl(const Interface& inf,
+      const Declaration& decl);
+  std::string GenDelegateParcelRead(const Interface& inf,
+      const Declaration& decl);
+  std::string GenDelegateArgsFree(const Interface& inf,
+      const Declaration& decl);
+  std::string GenDelegateCallbackArgs(const Declaration& decl);
+
+  std::string GenMethodAsyncBase(const Interface& inf, const Declaration& decl);
+  std::string GenMethodBase(const Interface& inf, const Declaration& decl);
+  std::string GenMethodParams(const Interface& inf, const Declaration& decl);
+  std::string GenMethodParamsCheck(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodParcelWrite(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodDelegateAppend(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodArgs(const Interface& inf, const Declaration& decl);
+  std::string GenMethodParcelReadBase(const Interface& inf,
+      const BaseType& type, const std::string& param_name);
+  std::string GenMethodParcelRead(const Interface& inf,
+      const Declaration& decl);
+
+  private:
+    std::shared_ptr<Options> options_;
 };
 
 }  // namespace tidl
index 0757b2d..54885ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_PROXY_BODY_GEN_CB_H_
 #define IDLC_C_GEN_C_PROXY_BODY_GEN_CB_H_
 
-const char CB_INTERFACE_STRUCT[] =
+constexpr const char CB_INTERFACE_DELEGATE_CALLBACK[] =
 R"__c_cb(
-struct ##_s {
-    char *stub_appid;
-    rpc_port_proxy_h proxy;
-    rpc_port_h port;
-    rpc_port_h callback_port;
-    rpc_port_proxy_##_callback_s callback;
-    void *user_data;
-    GList *delegates;
-    GRecMutex mutex;
-};
+typedef void (*rpc_port_proxy_delegate_cb)(GList **delegates, rpc_port_parcel_h parcel, int id, int seq_id);
 )__c_cb";
 
-const char CB_FILE_LIST_SHARING[] =
+/**
+ * <ENUMS> The enumeration of the interface delegate.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_ENUM_BASE[] =
 R"__c_cb(
-int __file_list_set_private_sharing(rpc_port_h port, GList *list_files) {
-       const char **arr = calloc(g_list_length(list_files), sizeof(char*));
-       GList *iter;
-       int idx = 0;
-       int r = 0;
-       iter = list_files;
-       while (iter) {
-               char *value = iter->data;
-               if (!value) {
-                       _W("Warning: value is NULL");
-                       continue;
-               }
-               arr[idx++] = value;
-               iter = g_list_next(iter);
-       }
-       if (idx > 0)
-               r = rpc_port_set_private_sharing_array(port, arr, idx);
-       return r;
-}
+typedef enum {
+  <ENUMS>
+} <PREFIX>_<NAME>_delegate_e;
 )__c_cb";
 
-const char CB_FILE_ARRAY_SHARING[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate of the interface.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_DEF[] =
 R"__c_cb(
-int __file_array_set_private_sharing(rpc_port_h port,
-               const char **files, int files_size) {
-       return rpc_port_set_private_sharing_array(port, files, files_size);
-}
+typedef struct <PREFIX>_<NAME>_<DELEGATE_NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  int id;
+  int seq_id;
+  bool once;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_cb callback;
+  void *user_data;
+} <PREFIX>_<NAME>_<DELEGATE_NAME>_t;
 )__c_cb";
 
-const char CB_DELEGATE_STRUCT[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate of the interface.
+ * <DELEGATE_ENUM_VALUE> The enumeration value of the delegate.
+ * <DELEGATE_ARGS_DECL> The implementation to declares the arguments.
+ * <DELEGATE_PARCEL_READ> The implementation to read the arguments from the parcel.
+ * <DELEGATE_ARGS_FREE> The implementation to release the allocated arguments.
+ * <DELEGATE_CALLBACK_ARGS> The arguments of the delegate callback.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BASE[] =
 R"__c_cb(
-struct ##_s {
-    rpc_port_parcelable_t parcelable;
-    int id;
-    int seq_id;
-    ## callback;
-    bool once;
-    void *user_data;
-};
-)__c_cb";
+static void __<PREFIX>_<NAME>_<DELEGATE_NAME>_to(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h h = data;
 
-const char CB_DELEGATE_SERIALIZER[] =
-R"__c_cb(
-static void __##_to(rpc_port_parcel_h parcel, void *data)
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
+
+  rpc_port_parcel_write_int32(parcel, h->id);
+
+  rpc_port_parcel_write_int32(parcel, h->seq_id);
+
+  rpc_port_parcel_write_bool(parcel, h->once);
+
+  _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false");
+}
+
+static void __<PREFIX>_<NAME>_<DELEGATE_NAME>_from(rpc_port_parcel_h parcel, void *data)
 {
-    struct ##_s *handle = data;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h h = data;
 
-    if (!handle) {
-        _E("Invalid parameter");
-        return;
-    }
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
 
-    rpc_port_parcel_write_int32(parcel, handle->id);
-    rpc_port_parcel_write_int32(parcel, handle->seq_id);
-    rpc_port_parcel_write_bool(parcel, handle->once);
-    _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false");
+  rpc_port_parcel_read_int32(parcel, &h->id);
+
+  rpc_port_parcel_read_int32(parcel, &h->seq_id);
+
+  rpc_port_parcel_read_bool(parcel, &h->once);
+
+  _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false");
+  set_last_result(RPC_PORT_ERROR_NONE);
 }
-)__c_cb";
 
-const char CB_DELEGATE_DESERIALIZER[] =
-R"__c_cb(
-static void __##_from(rpc_port_parcel_h parcel, void *data)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_create(<PREFIX>_<NAME>_<DELEGATE_NAME>_h *h)
 {
-    struct ##_s *handle = data;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_t *handle;
+  static int seq_num;
 
-    if (!handle) {
-        _E("Invalid parameter");
-        return;
-    }
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_<DELEGATE_NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->parcelable.to = __<PREFIX>_<NAME>_<DELEGATE_NAME>_to;
+  handle->parcelable.from = __<PREFIX>_<NAME>_<DELEGATE_NAME>_from;
+  handle->id = <DELEGATE_ENUM_VALUE>;
+  handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1;
+  _I("id(%d), seq_id(%d)", handle->id, handle->seq_id);
 
-    rpc_port_parcel_read_int32(parcel, &handle->id);
-    rpc_port_parcel_read_int32(parcel, &handle->seq_id);
-    rpc_port_parcel_read_bool(parcel, &handle->once);
-    _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false");
+  *h = handle;
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_DELEGATE_CTOR[] =
-R"__c_cb(
-rpc_port_##_h rpc_port_##_create(## callback, bool once, void *user_data)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h)
 {
-    struct ##_s *handle;
-    static int seq_num;
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    handle = calloc(1, sizeof(struct ##_s));
-    if (!handle) {
-        _E("Out of memory");
-        return NULL;
-    }
+  _W("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false");
 
-    handle->parcelable.to = __##_to;
-    handle->parcelable.from= __##_from;
-    handle->id = $$_DELEGATE_$$;
-    handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1;
-    handle->callback = callback;
-    handle->once = once;
-    handle->user_data = user_data;
-    _I("id(%d), seq_id(%d)", handle->id, handle->seq_id);
+  free(h);
 
-    return handle;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_DELEGATE_DISPOSER[] =
-R"__c_cb(
-int rpc_port_proxy_##_dispose(rpc_port_proxy_$$_h proxy, rpc_port_##_h delegate)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_clone(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, <PREFIX>_<NAME>_<DELEGATE_NAME>_h *clone)
 {
-    struct ##_s *handle;
-    GList *iter;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h handle;
+  rpc_port_parcel_h parcel;
+  int ret;
+
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = <PREFIX>_<NAME>_<DELEGATE_NAME>_create(&handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    return ret;
+  }
+
+  ret = rpc_port_parcel_create(&parcel);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", ret);
+    <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(handle);
+    return ret;
+  }
+
+  rpc_port_parcel_write(parcel, &h->parcelable, h);
+  rpc_port_parcel_read(parcel, &handle->parcelable, handle);
+  ret = get_last_result();
+  rpc_port_parcel_destroy(parcel);
+
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read data. error(%d)", ret);
+    <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(handle);
+    return ret;
+  }
+
+  *clone = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
 
-    if (!proxy || !delegate) {
-        _E("Invalid handle %p %p", proxy, delegate);
-        return -1;
-    }
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_set_callback(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, <PREFIX>_<NAME>_<DELEGATE_NAME>_cb callback, void *user_data)
+{
+  if (h == nullptr || callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    iter = proxy->delegates;
-    while (iter) {
-        handle = (struct ##_s *)iter->data;
-        if (handle == delegate) {
-            _W("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false");
-            proxy->delegates = g_list_remove_link(proxy->delegates, iter);
-            free(handle);
-            g_list_free(iter);
-            return 0;
-        }
-        iter = g_list_next(iter);
-    }
+  h->callback = callback;
+  h->user_data = user_data;
 
-    return -1;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_DELEGATE_DTOR[] =
-R"__c_cb(
-int rpc_port_##_destroy(rpc_port_##_h delegate)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_set_once(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, bool once)
 {
-    if (!delegate) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    free(delegate);
+  h->once = once;
 
-    return 0;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_DELEGATE_INVOKER[] =
-R"__c_cb(
-static void __$$_delegate_$$(GList **list, rpc_port_parcel_h parcel, int seq_id, int id)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *id)
 {
-$$
-    do {
-        struct ##_s *handle;
-        GList *iter;
-
-        iter = *list;
-        while (iter) {
-            handle = (struct ##_s *)iter->data;
-            if (handle->seq_id == seq_id && handle->id == id) {
-                bool once = handle->once;
-
-                _W("Invoke id(%d), seq_id(%d)", id, seq_id);
-                $$
-                if (once) {
-                    _W("Dispose");
-                    *list = g_list_remove_link(*list, iter);
-                    free(handle);
-                    g_list_free(iter);
-                }
-                break;
-            }
-            iter = g_list_next(iter);
-        }
-    } while (0);
-$$
+  if (h == nullptr || id == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  *id = h->id;
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_PROCESS_RECEIVED_EVENT[] =
-R"__c_cb(
-static void __##_process_received_event(GList **list, rpc_port_parcel_h parcel)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_seq_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *seq_id)
 {
-$$
+  if (h == nullptr || seq_id == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  *seq_id = h->seq_id;
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_PROCESS_RECEIVED_EVENT_IMPL[] =
-R"__c_cb(int id;
-int seq_id;
-bool once;
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_is_once(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, bool *once)
+{
+  if (h == nullptr || once == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-rpc_port_parcel_read_int32(parcel, &id);
-rpc_port_parcel_read_int32(parcel, &seq_id);
-rpc_port_parcel_read_bool(parcel, &once);
-_W("id(%d), seq_id(%d)", id, seq_id);
+  *once = h->once;
 
-if (id > 0 && id < (sizeof(__##_delegate_table) / sizeof(__##_delegate_table[0]))) {
-    if (__##_delegate_table[id])
-        __##_delegate_table[id](list, parcel, seq_id, id);
-} else {
-    _W("Unknown id(%d)", id);
-})__c_cb";
+  return RPC_PORT_ERROR_NONE;
+}
 
-const char CB_CONSUME_COMMAND[] =
-R"__c_cb(
-static rpc_port_parcel_h __##_consume_command(rpc_port_proxy_##_h h)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_tag(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, char **tag)
 {
-    rpc_port_parcel_h parcel = NULL;
-    int cmd = -1;
+  char *new_tag;
+  char buf[128];
 
-    do {
-        rpc_port_parcel_create_from_port(&parcel, h->port);
-        if (!parcel)
-            break;
+  if (h == nullptr || tag == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-        rpc_port_parcel_read_int32(parcel, &cmd);
-        if (cmd == ##_METHOD_Result)
-            return parcel;
+  snprintf(buf, sizeof(buf), "%d::%d", h->id, h->seq_id);
+  new_tag = strdup(buf);
+  if (new_tag == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
 
-        rpc_port_parcel_destroy(parcel);
-        parcel = NULL;
-    } while (true);
+  *tag = new_tag;
 
-    return NULL;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_ON_CONNECTED[] =
-R"__c_cb(
-static void __##_on_connected(const char *endpoint, const char *port_name, rpc_port_h port, void *data)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_dispose(<PREFIX>_<NAME>_h proxy, <PREFIX>_<NAME>_<DELEGATE_NAME>_h h)
+{
+  GList *found;
+
+  if (proxy == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  found = g_list_find(proxy->delegates, h);
+  if (found == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  proxy->delegates = g_list_remove_link(proxy->delegates, found);
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(h);
+  g_list_free(found);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+static void __<PREFIX>_<NAME>_<DELEGATE_NAME>_delegate_handler(GList **delegates, rpc_port_parcel_h parcel, int id, int seq_id)
 {
-    rpc_port_proxy_##_h handle = data;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h handle;
+  GList *iter;
+  bool once;
+  <DELEGATE_ARGS_DECL>
+
+  <DELEGATE_PARCEL_READ>
+
+  iter = *delegates;
+  while (iter) {
+    handle = iter->data;
+    iter = g_list_next(iter);
+    if (handle->id == id && handle->seq_id == seq_id) {
+      once = handle->once;
+      _W("Invoke id(%d), seq_id(%d)", id, seq_id);
+      if (handle->callback)
+        handle->callback(handle->user_data<DELEGATE_CALLBACK_ARGS>);
+      else
+        _W("The callback function is nullptr");
+
+      if (once) {
+        *delegates = g_list_remove(*delegates, handle);
+        <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(handle);
+      }
+
+      break;
+    }
+  }
 
-    handle->port = port;
-    rpc_port_proxy_get_port(handle->proxy, RPC_PORT_PORT_CALLBACK, &handle->callback_port);
-    if (handle->callback.connected)
-        handle->callback.connected(handle, handle->user_data);
-    _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name);
+out:
+  <DELEGATE_ARGS_FREE>
 }
 )__c_cb";
 
-const char CB_ON_DISCONNECTED[] =
+/**
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_READ[] =
 R"__c_cb(
-static void __##_on_disconnected(const char *endpoint, const char *port_name, void *data)
-{
-    rpc_port_proxy_##_h handle = data;
+<PREFIX>_<NAME>_create(&<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to create handle");
+  goto out;
+}
 
-    handle->port = NULL;
-    if (handle->callback.disconnected)
-        handle->callback.disconnected(handle, handle->user_data);
-    _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name);
+rpc_port_parcel_read(parcel, &<ARG>->parcelable, <ARG>);
+if (get_last_result() != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data");
+  goto out;
 }
 )__c_cb";
 
-const char CB_ON_REJECTED[] =
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_READ[] =
 R"__c_cb(
-static void __##_on_rejected(const char *endpoint, const char *port_name, void *data)
-{
-    rpc_port_proxy_##_h handle = data;
+rpc_port_parcel_read_bundle(parcel, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  goto out;
+}
+)__c_cb";
 
-    handle->port = NULL;
-    if (handle->callback.rejected)
-        handle->callback.rejected(handle, handle->user_data);
-    _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name);
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_STRING_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_string(parcel, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  goto out;
 }
 )__c_cb";
 
-const char CB_ON_RECEIVED[] =
+/**
+ * <PARCEL_TYPE> The type of the parcel.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BASE_PARCEL_READ[] =
 R"__c_cb(
-static void __##_on_received(const char *endpoint, const char *port_name, void *data)
-{
-    rpc_port_proxy_##_h handle = data;
-    rpc_port_parcel_h parcel_received = NULL;
-    int cmd = -1;
-
-    rpc_port_parcel_create_from_port(&parcel_received, handle->callback_port);
-    if (!parcel_received) {
-        _E("Failed to create parcel from port(%s)", port_name);
-        return;
-    }
+rpc_port_parcel_read_<PARCEL_TYPE>(parcel, &<ARG>);
+)__c_cb";
 
-    rpc_port_parcel_read_int32(parcel_received, &cmd);
-    if (cmd != ##_METHOD_Callback) {
-        _E("Invalid protocol");
-        rpc_port_parcel_destroy(parcel_received);
-        return;
-    }
+/**
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_USER_DEFINED_ARG_FREE[] =
+R"__c_cb(
+if (<ARG>)
+  <PREFIX>_<NAME>_destroy(<ARG>);
+)__c_cb";
 
-    __##_process_received_event(&handle->delegates, parcel_received);
-    rpc_port_parcel_destroy(parcel_received);
-    _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name);
-}
+/**
+ * <ARG> The name of the value.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE[] =
+R"__c_cb(
+if (<ARG>)
+  bundle_free(<ARG>);
 )__c_cb";
 
-const char CB_INTERFACE_METHODS[] =
+/**
+ * <ARG> The name of the value;
+ */
+constexpr const char CB_INTERFACE_DELEGATE_STRING_ARG_FREE[] =
 R"__c_cb(
-$$rpc_port_proxy_##_invoke_$$(rpc_port_proxy_##_h h$$)
-{
-    rpc_port_parcel_h parcel;
-    int r;
-$$
+if (<ARG>)
+  free(<ARG>);
+)__c_cb";
 
-    if (!h$$) {
-        _E("Invalid parameter");
-        return$$;
-    }
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_HANDLERS> The array of the delegate callbacks.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_TABLE[] =
+R"__c_cb(
+static <PREFIX>_delegate_cb __<PREFIX>_<NAME>_delegate_table[] = {
+  <DELEGATE_HANDLERS>
+};
+)__c_cb";
 
-    if (!h->port) {
-        _E("Not connected");
-        return$$;
-    }
-$$
-    rpc_port_parcel_create(&parcel);
-    rpc_port_parcel_write_int32(parcel, ##_METHOD_$$);
-$$
-    r = rpc_port_parcel_send(parcel, h->port);
-    if (r != RPC_PORT_ERROR_NONE) {
-        _E("Failed to send parcel. result(%d)", r);
-        r = RPC_PORT_ERROR_IO_ERROR;
-    }
+/**
+ * <ENUM_VALUE> The enumeration value.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate of the interface.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_TABLE_MEMBER[] =
+R"__c_cb(
+[<ENUM_VALUE>] = __<PREFIX>_<NAME>_<DELEGATE_NAME>_delegate_handler,
+)__c_cb";
 
-    rpc_port_parcel_destroy(parcel);
-$$
-}
+/**
+ * <ENUMS> The enumerations of the interface method.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_ENUM_BASE[] =
+R"__c_cb(
+typedef enum {
+  <ENUMS>
+} <PREFIX>_<NAME>_method_e;
 )__c_cb";
 
-const char CB_INTERFACE_HANDLE_CTOR[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_BASE_DEF[] =
 R"__c_cb(
-static struct ##_s *__create_##(const char *stub_appid, rpc_port_proxy_##_callback_s *callback, void *user_data)
-{
-    struct ##_s *handle;
+typedef struct <PREFIX>_<NAME>_s {
+  char *stub_appid;
+  rpc_port_proxy_h proxy;
+  rpc_port_h port;
+  rpc_port_h callback_port;
+  <PREFIX>_<NAME>_callback_s callback;
+  void *user_data;
+  GList *delegates;
+  GRecMutex mutex;
+} <PREFIX>_<NAME>_t;
+)__c_cb";
 
-    handle = calloc(1, sizeof(struct ##_s));
-    if (!handle) {
-        _E("Out of memory");
-        return NULL;
-    }
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <UPPERCASE_PREFIX> The uppercase prefix of the interface.
+ * <UPPERCASE_NAME> The uppercase name of the interface.
+ */
+constexpr const char CB_INTERFACE_BASE[] =
+R"__c_cb(
+static void __<PREFIX>_<NAME>_process_received_event(GList **delegates, 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);
+  _W("id(%d), seq_id(%d)", id, seq_id);
+
+  if (id > 0 && id < ARRAY_SIZE(__<PREFIX>_<NAME>_delegate_table)) {
+    if (__<PREFIX>_<NAME>_delegate_table[id])
+      __<PREFIX>_<NAME>_delegate_table[id](delegates, parcel, id, seq_id);
+  } else {
+    _W("Unknown ID(%d)", id);
+  }
+}
 
-    handle->stub_appid = strdup(stub_appid);
-    if (!handle->stub_appid) {
-        _E("Out of memory");
-        free(handle);
-        return NULL;
+static void __<PREFIX>_<NAME>_consume_command(rpc_port_h port, rpc_port_parcel_h *p)
+{
+  rpc_port_parcel_h parcel;
+  int cmd = -1;
+  int ret;
+
+  do {
+    ret = rpc_port_parcel_create_from_port(&parcel, port);
+    if (ret != RPC_PORT_ERROR_NONE)
+      break;
+
+    rpc_port_parcel_read_int32(parcel, &cmd);
+    if (cmd == <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_RESULT_) {
+      *p = parcel;
+      return;
     }
 
-    rpc_port_proxy_create(&handle->proxy);
-    if (!handle->proxy) {
-        _E("Failed to create proxy");
-        free(handle->stub_appid);
-        free(handle);
-        return NULL;
-    }
+    rpc_port_parcel_destroy(parcel);
+  } while (true);
 
-    g_rec_mutex_init(&handle->mutex);
+  *p = nullptr;
+}
 
-    handle->callback = *callback;
-    handle->user_data = user_data;
+static void __<PREFIX>_<NAME>_connected(const char *endpoint, const char *port_name, rpc_port_h port, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
 
-    return handle;
+  _I("endpoint(%s), port_name(%s)", endpoint, port_name);
+  h->port = port;
+  rpc_port_proxy_get_port(h->proxy, RPC_PORT_PORT_CALLBACK, &h->callback_port);
+  h->callback.connected(h, h->user_data);
 }
-)__c_cb";
 
-const char CB_INTERFACE_HANDLE_DTOR[] =
-R"__c_cb(
-static void __destroy_##(struct ##_s *h)
+static void __<PREFIX>_<NAME>_disconnected(const char *endpoint, const char *port_name, void *data)
 {
-    if (!h)
-        return;
+  <PREFIX>_<NAME>_h h = data;
 
-    g_rec_mutex_clear(&h->mutex);
+  _W("endpoint(%s), port_name(%s)", endpoint, port_name);
+  h->port = nullptr;
+  h->callback.disconnected(h, h->user_data);
 
-    if (h->delegates)
-        g_list_free_full(h->delegates, free);
+}
 
-    if (h->proxy)
-        rpc_port_proxy_destroy(h->proxy);
+static void __<PREFIX>_<NAME>_rejected(const char *endpoint, const char *port_name, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
 
-    if (h->stub_appid)
-        free(h->stub_appid);
+  _W("endpoint(%s), port_name(%s)", endpoint, port_name);
+  h->port = nullptr;
+  h->callback.rejected(h, h->user_data);
+}
 
-    free(h);
+static void __<PREFIX>_<NAME>_received(const char *endpoint, const char *port_name, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  rpc_port_parcel_h parcel;
+  int cmd = -1;
+  int ret;
+
+  _W("endpoint(%s), port_name(%s)", endpoint, port_name);
+  ret = rpc_port_parcel_create_from_port(&parcel, h->callback_port);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle from port. error(%d)", ret);
+    return;
+  }
+
+  rpc_port_parcel_read_int32(parcel, &cmd);
+  if (cmd != <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_CALLBACK_) {
+    _E("Invalid protocol");
+    rpc_port_parcel_destroy(parcel);
+    return;
+  }
+
+  __<PREFIX>_<NAME>_process_received_event(&h->delegates, parcel);
+  rpc_port_parcel_destroy(parcel);
 }
-)__c_cb";
 
-const char CB_INTERFACE_CTOR[] =
-R"__c_cb(
-int rpc_port_proxy_##_create(const char *stub_appid, rpc_port_proxy_##_callback_s *callback, void *user_data, rpc_port_proxy_##_h *h)
+int <PREFIX>_<NAME>_create(const char *stub_appid, <PREFIX>_<NAME>_callback_s *callback, void *user_data, <PREFIX>_<NAME>_h *h)
+{
+  <PREFIX>_<NAME>_t *handle;
+  int ret;
+
+  if (stub_appid == nullptr || callback == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  if (callback->connected == nullptr || callback->disconnected == nullptr || callback->rejected == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  g_rec_mutex_init(&handle->mutex);
+
+  handle->stub_appid = strdup(stub_appid);
+  if (handle->stub_appid == nullptr) {
+    _E("Failed to duplicate stub appid");
+    <PREFIX>_<NAME>_destroy(handle);
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  ret = rpc_port_proxy_create(&handle->proxy);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create proxy handle. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  handle->callback = *callback;
+  handle->user_data = user_data;
+
+  ret = rpc_port_proxy_add_connected_event_cb(handle->proxy, __<PREFIX>_<NAME>_connected, handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add connected event cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  ret = rpc_port_proxy_add_disconnected_event_cb(handle->proxy, __<PREFIX>_<NAME>_disconnected, handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add disconnected event cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  ret = rpc_port_proxy_add_rejected_event_cb(handle->proxy, __<PREFIX>_<NAME>_rejected, handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add rejected event cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  ret = rpc_port_proxy_add_received_event_cb(handle->proxy, __<PREFIX>_<NAME>_received, handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add received event cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  *h = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h)
 {
-    struct ##_s *handle;
-    int r;
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    if (!stub_appid || !callback || !h) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  g_rec_mutex_lock(&h->mutex);
+  g_rec_mutex_unlock(&h->mutex);
+  g_rec_mutex_clear(&h->mutex);
 
-    handle = __create_##(stub_appid, callback, user_data);
-    if (!handle)
-        return -1;
+  if (h->delegates)
+    g_list_free_full(h->delegates, free);
 
-    r = rpc_port_proxy_add_connected_event_cb(handle->proxy, __##_on_connected, handle);
-    if (r != 0) {
-        _E("Failed to add connected event cb. err = %d", r);
-        __destroy_##(handle);
-        return r;
-    }
+  if (h->proxy)
+    rpc_port_proxy_destroy(h->proxy);
 
-    r = rpc_port_proxy_add_disconnected_event_cb(handle->proxy, __##_on_disconnected, handle);
-    if (r != 0) {
-        _E("Failed to add disconnected event cb. err = %d", r);
-        __destroy_##(handle);
-        return r;
-    }
+  if (h->stub_appid)
+    free(h->stub_appid);
 
-    r = rpc_port_proxy_add_rejected_event_cb(handle->proxy, __##_on_rejected, handle);
-    if (r != 0) {
-        _E("Failed to add rejected event cb. err = %d", r);
-        __destroy_##(handle);
-        return r;
-    }
+  free(h);
 
-    r = rpc_port_proxy_add_received_event_cb(handle->proxy, __##_on_received, handle);
-    if (r != 0) {
-        _E("Failed to add received event cb. err = %d", r);
-        __destroy_##(handle);
-        return r;
-    }
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_connect(<PREFIX>_<NAME>_h h)
+{
+  int ret;
+
+  if (h == nullptr || h->proxy == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    *h = handle;
+  ret = rpc_port_proxy_connect(h->proxy, h->stub_appid, "<NAME>");
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to connect to stub. error(%d)", ret);
+    return ret;
+  }
 
-    return 0;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_CONNECT[] =
-R"__c_cb(
-int rpc_port_proxy_##_connect(rpc_port_proxy_##_h h)
+int <PREFIX>_<NAME>_connect_sync(<PREFIX>_<NAME>_h h)
 {
-    int r;
+  int ret;
 
-    if (!h || !h->proxy) {
-        _E("Invalid parameter");
-       return -1;
-    }
+  if (h == nullptr || h->proxy == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    r = rpc_port_proxy_connect(h->proxy, h->stub_appid, "##");
-    if (r != 0) {
-        _E("Failed to connect ##(%s)", h->stub_appid);
-       return r;
-    }
+  ret = rpc_port_proxy_connect_sync(h->proxy, h->stub_appid, "<NAME>");
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to connect to stub. error(%d)", ret);
+    return ret;
+  }
 
-    return 0;
+  return RPC_PORT_ERROR_NONE;
 }
 )__c_cb";
 
-const char CB_INTERFACE_DTOR[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_NAME> The method name of the interface.
+ * <METHOD_PARAMS> The parameters of the method of the interface
+ * <METHOD_PARAMS_CHECK> The parameters check of the method.
+ * <UPPERCASE_PREFIX> The uppercase prefix of the interface.
+ * <UPPERCASE_NAME> The uppercase name of the interface.
+ * <UPPERCASE_METHOD_NAME> The uppercase method name of the interface.
+ * <METHOD_PARCEL_WRITE> The implementation to write arguments to the parcel.
+ * <METHOD_DELEGATES_APPEND> The implementation to add the delegates to the list.
+ */
+constexpr const char CB_INTERFACE_METHOD_ASYNC_BASE[] =
+R"__c_cb(
+void <PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>)
+{
+  rpc_port_parcel_h parcel_;
+  int res_;
+
+  if (h == nullptr<METHOD_PARAMS_CHECK>) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  g_rec_mutex_lock(&h->mutex);
+  if (h->port == nullptr) {
+    _E("Not connected");
+    g_rec_mutex_unlock(&h->mutex);
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  res_ = rpc_port_parcel_create(&parcel_);
+  if (res_ != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", res_);
+    g_rec_mutex_unlock(&h->mutex);
+    set_last_result(res_);
+    return;
+  }
+
+  rpc_port_parcel_write_int32(parcel_, <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_<UPPERCASE_METHOD_NAME>);
+
+  <METHOD_PARCEL_WRITE>
+  <METHOD_DELEGATE_APPEND>
+
+  res_ = rpc_port_parcel_send(parcel_, h->port);
+  rpc_port_parcel_destroy(parcel_);
+  if (res_ != RPC_PORT_ERROR_NONE)
+    _E("Failed to send parcel. error(%d)", res_);
+
+  g_rec_mutex_unlock(&h->mutex);
+  set_last_result(res_);
+}
+)__c_cb";
+
+/**
+ * <RETURN_TYPE> The return type of the method of the interface.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_NAME> The method name of the interface.
+ * <METHOD_ARGS> The value declarations for reading the data from the parcel.
+ * <ERROR_VALUE> The error value of the method.
+ * <METHOD_PARAMS> The parameters of the method of the interface.
+ * <METHOD_PARAMS_CHECK> The parameters check of the method.
+ * <UPPERCASE_PREFIX> The uppercase prefix of the interface.
+ * <UPPERCASE_NAME> The uppercase name of the interface.
+ * <UPPERCASE_METHOD_NAME> The uppercase method name of the interface.
+ * <METHOD_PARCEL_WRITE> The implementation to write arguments to the parcel.
+ * <METHOD_PARCEL_READ> The implementation to read results from the parcel.
+ * <METHOD_DELEGATE_APPEND> The implementation to add the delegates to the list.
+ */
+constexpr const char CB_INTERFACE_METHOD_BASE[] =
 R"__c_cb(
-int rpc_port_proxy_##_destroy(rpc_port_proxy_##_h h)
+<RETURN_TYPE><PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>)
 {
-    if (!h) {
-        _E("Invalid parameter");
-        return -1;
+  rpc_port_parcel_h parcel_;
+  int res_;
+  <RETURN_TYPE>ret_ = <ERROR_VALUE>;
+  <METHOD_ARGS>
+
+  if (h == nullptr<METHOD_PARAMS_CHECK>) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return ret_;
+  }
+
+  g_rec_mutex_lock(&h->mutex);
+  if (h->port == nullptr) {
+    _E("Not connected");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    g_rec_mutex_unlock(&h->mutex);
+    return ret_;
+  }
+
+  res_ = rpc_port_parcel_create(&parcel_);
+  if (res_ != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", res_);
+    set_last_result(res_);
+    g_rec_mutex_unlock(&h->mutex);
+    return ret_;
+  }
+
+  rpc_port_parcel_write_int32(parcel_, <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_<UPPERCASE_METHOD_NAME>);
+
+  <METHOD_PARCEL_WRITE>
+  <METHOD_DELEGATE_APPEND>
+
+  res_ = rpc_port_parcel_send(parcel_, h->port);
+  rpc_port_parcel_destroy(parcel_);
+  if (res_ != RPC_PORT_ERROR_NONE) {
+    _E("Failed to send parcel. error(%d)", res_);
+    set_last_result(res_);
+    g_rec_mutex_unlock(&h->mutex);
+    return ret_;
+  }
+
+  do {
+    parcel_ = nullptr;
+    __<PREFIX>_<NAME>_consume_command(h->port, &parcel_);
+    if (parcel_ == nullptr) {
+      _E("Invalid protocol");
+      res_ = RPC_PORT_ERROR_IO_ERROR;
+      break;
     }
 
-    __destroy_##(h);
-    return 0;
+    <METHOD_PARCEL_READ>
+    rpc_port_parcel_destroy(parcel_);
+  } while (0);
+  g_rec_mutex_unlock(&h->mutex);
+  set_last_result(res_);
+
+  return ret_;
 }
 )__c_cb";
 
-const char CB_DELEGATE_BLOCK[] =
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE[] =
 R"__c_cb(
-do {
-    struct ##_s *handle = $$;
-
-    rpc_port_parcel_write(parcel, &handle->parcelable, handle);
-    h->delegates = g_list_append(h->delegates, handle);
-} while (0);
+rpc_port_parcel_write(parcel_, &<ARG>->parcelable, <ARG>);
 )__c_cb";
 
-const char CB_RECEIVE_BLOCK[] =
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE[] =
 R"__c_cb(
-g_rec_mutex_lock(&h->mutex);
-do {
-    rpc_port_parcel_h parcel_received;
-$$
-    parcel_received = __$$_consume_command(h);
-    if (!parcel_received) {
-        _E("Invalid protocol");
-        r = RPC_PORT_ERROR_IO_ERROR;
-        break;
-    }
+rpc_port_parcel_write_bundle(parcel_, <ARG>);
+)__c_cb";
 
-$$
-    rpc_port_parcel_destroy(parcel_received);
-} while (0);
-g_rec_mutex_unlock(&h->mutex);
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_string(parcel_, <ARG>);
 )__c_cb";
 
-const char CB_LIST_PRIVATE_SHARING_BLOCK[] =
+/**
+ * <PARCEL_TYPE> The type of the parcel.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_WRITE[] =
 R"__c_cb(
-    r = __file_list_set_private_sharing(h->port, ##->list_files);
-    if (r != RPC_PORT_ERROR_NONE) {
-        _E("Fail to set private sharing");
-        return ret;
-    }
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel_, <ARG>);
 )__c_cb";
 
-const char CB_ARRAY_PRIVATE_SHARING_BLOCK[] =
+/**
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ[] =
 R"__c_cb(
-    r = __file_array_set_private_sharing(h->port,
-                       (const char **)##->array_files, ##->array_files_size);
-    if (r != RPC_PORT_ERROR_NONE) {
-        _E("Fail to set private sharing");
-        return ret;
-    }
+<ARG> = nullptr;
+<PREFIX>_<NAME>_create(&<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to create handle");
+  res_ = RPC_PORT_ERROR_OUT_OF_MEMORY;
+  break;
+}
+
+rpc_port_parcel_read(parcel_, &<ARG>->parcelable, <ARG>);
+if (get_last_result() != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data");
+  <PREFIX>_<NAME>_destroy(<ARG>);
+  res_ = get_last_result();
+  break;
+}
 )__c_cb";
 
-const char CB_PRIVATE_SHARING_BLOCK[] =
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ[] =
 R"__c_cb(
-    r = rpc_port_set_private_sharing(h->port, ##);
-       if (r != RPC_PORT_ERROR_NONE) {
-               _E("Fail to set private sharing");
-               return ret;
-       }
+<ARG> = nullptr;
+rpc_port_parcel_read_bundle(parcel_, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  res_ = RPC_PORT_ERROR_OUT_OF_MEMORY;
+  break;
+}
 )__c_cb";
 
-const char CB_INTERFACE_CONNECT_SYNC[] =
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] =
 R"__c_cb(
-int rpc_port_proxy_##_connect_sync(rpc_port_proxy_##_h h)
-{
-    int r;
+<ARG> = nullptr;
+rpc_port_parcel_read_string(parcel_, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  res_ = RPC_PORT_ERROR_OUT_OF_MEMORY;
+  break;
+}
+)__c_cb";
 
-    if (!h || !h->proxy) {
-        _E("Invalid parameter");
-        return -1;
-    }
+/**
+ * <PARCEL_TYPE> The type of the parcel.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_<PARCEL_TYPE>(parcel_, &<ARG>);
+)__c_cb";
 
-    r = rpc_port_proxy_connect_sync(h->proxy, h->stub_appid, "##");
-    if (r != 0) {
-        _E("Failed to connect sync ##(%s)", h->stub_appid);
-        return r;
-    }
+/**
+ * <PARAM> The name of the parameter.
+ */
+constexpr const char CB_INTERFACE_METHOD_PARAM_SET[] =
+R"__c_cb(
+*<PARAM> = new_<PARAM>;
+)__c_cb";
 
-    return 0;
-}
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_DELEGATE_APPEND[] =
+R"__c_cb(
+h->delegates = g_list_append(h->delegates, <ARG>);
 )__c_cb";
 
 #endif  // IDLC_C_GEN_C_PROXY_BODY_GEN_CB_H_
index b5bca94..4c52398 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
@@ -23,13 +23,16 @@ namespace {
 namespace tidl {
 
 CProxyHeaderGen::CProxyHeaderGen(std::shared_ptr<Document> doc)
-    : CHeaderGeneratorBase(doc) {}
+    : CHeaderGeneratorBase(doc) {
+}
 
 void CProxyHeaderGen::OnInitGen(std::ofstream& stream) {
   GenVersion(stream);
   GenPragmaOnce(stream);
   GenIncludeDefaultHeaders(stream, false);
   GenExplicitLinkageOpen(stream);
+  GenStructureHandles(stream);
+  GenInterfaceHandles(stream);
   GenStructures(stream);
   GenInterfaces(stream);
 }
@@ -38,6 +41,43 @@ void CProxyHeaderGen::OnFiniGen(std::ofstream& stream) {
   GenExplicitLinkageClose(stream);
 }
 
+void CProxyHeaderGen::GenInterfaceHandles(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& inf = static_cast<const Interface&>(*b);
+    GenInterfaceHandle(stream, inf);
+    for (auto& d : inf.GetDeclarations().GetDecls()) {
+      if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+        continue;
+
+      GenInterfaceDelegateHandle(stream, inf, *d);
+    }
+  }
+}
+
+// @see #CB_INTERFACE_HANDLE
+void CProxyHeaderGen::GenInterfaceHandle(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_HANDLE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_DELEGATE_HANDLE
+void CProxyHeaderGen::GenInterfaceDelegateHandle(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_HANDLE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+
+  stream << SmartIndent(code);
+}
+
 void CProxyHeaderGen::GenInterfaces(std::ofstream& stream) {
   for (auto& i : GetDocument().GetBlocks()) {
     if (i->GetType() != Block::TYPE_INTERFACE)
@@ -49,127 +89,85 @@ void CProxyHeaderGen::GenInterfaces(std::ofstream& stream) {
 }
 
 void CProxyHeaderGen::GenInterface(std::ofstream& stream,
-                                   const Interface& inf) {
-  GenInterfaceDeclaration(stream, inf);
-  GenInterfaceDelegators(stream, inf);
-  GenInterfaceCtor(stream, inf);
-  GenInterfaceConnect(stream, inf);
-  GenInterfaceDtor(stream, inf);
-  GenInterfaceMethods(stream, inf);
-  GenInterfaceConnectSync(stream, inf);
-}
+    const Interface& inf) {
+  for (auto& d: inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenInterfaceDelegateBase(stream, inf, *d);
+  }
+
+  GenInterfaceBase(stream, inf);
 
-void CProxyHeaderGen::GenInterfaceDelegators(std::ofstream& stream,
-                                             const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
       continue;
-    GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i);
+
+    GenInterfaceMethodBase(stream, inf, *d);
   }
 }
 
-void CProxyHeaderGen::GenInterfaceDelegator(std::ofstream& stream,
-                                            const std::string& id,
-                                            const Declaration& decl) {
-  const char handle[] = "typedef struct $$_s *rpc_port_$$_h;";
-
-  stream << NLine(1);
-  stream << GenTemplateString(handle,
-      [&]()->std::string {
-        return id + "_" + decl.GetID();
-      },
-      [&]()->std::string {
-        return id + "_" + decl.GetID();
-      });
-
-  stream << NLine(1);
-  stream << GenTemplateString(CB_INTERFACE_DELEGATOR,
-      [&]()->std::string {
-        return GetReturnTypeString(decl.GetType());
-      },
-      [&]()->std::string {
-        return id + "_" + decl.GetID();
-      },
-      [&]()->std::string {
-        std::string str;
-        str += "void *user_data";
-        for (auto& p : decl.GetParameters().GetParams()) {
-          str += ", ";
-          str += GetParamTypeString(p->GetParameterType().GetDirection(),
-              p->GetParameterType().GetBaseType()) + p->GetID();
-        }
-        return str;
-      });
-
-  stream << ReplaceAll(CB_DELEGATE_CTOR, "##", id + "_" + decl.GetID());
-  stream << ReplaceAll(CB_DELEGATE_DTOR, "##", id + "_" + decl.GetID());
-  stream << GenTemplateString(
-      ReplaceAll(CB_DELEGATE_DISPOSER, "##", id + "_" + decl.GetID()),
-      [&]()->std::string {
-        return id;
-      });
-}
+// @see #CB_INTERFACE_BASE
+void CProxyHeaderGen::GenInterfaceBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
 
-void CProxyHeaderGen::GenInterfaceDeclaration(std::ofstream& stream,
-                                              const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_DECL, "##",
-      GetInterfaceIdWithNamespace(inf)));
+  stream << SmartIndent(code);
 }
 
-void CProxyHeaderGen::GenInterfaceMethods(std::ofstream& stream,
-                                          const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
-      continue;
-    stream << GenTemplateString(
-        ReplaceAll(CB_INTERFACE_METHODS, "##",
-            GetInterfaceIdWithNamespace(inf)),
-        [&]()->std::string {
-          return GetReturnTypeString(i->GetType());
-        },
-        [&]()->std::string {
-          return i->GetID();
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& p : i->GetParameters().GetParams()) {
-            str += ", ";
-            if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) {
-              str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" +
-                  p->GetParameterType().GetBaseType().ToString() +
-                  "_h " + p->GetID();
-            } else {
-              str += GetParamTypeString(p->GetParameterType().GetDirection(),
-                  p->GetParameterType().GetBaseType()) + p->GetID();
-            }
-          }
-          return str;
-        });
+std::string CProxyHeaderGen::GenDelegateParams(const Interface& inf,
+    const Declaration& decl) {
+  std::string params;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, inf) +
+        p->GetID();
   }
-}
 
-void CProxyHeaderGen::GenInterfaceCtor(std::ofstream& stream,
-                                          const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CTOR, "##",
-      GetInterfaceIdWithNamespace(inf));
+  return params;
 }
 
-void CProxyHeaderGen::GenInterfaceConnect(std::ofstream& stream,
-                                          const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CONNECT, "##",
-      GetInterfaceIdWithNamespace(inf));
+// @see #CB_INTERFACE_DELEGATE_BASE
+void CProxyHeaderGen::GenInterfaceDelegateBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+  code = ReplaceAll(code, "<DELEGATE_PARAMS>", GenDelegateParams(inf, decl));
+
+  stream << SmartIndent(code);
 }
 
-void CProxyHeaderGen::GenInterfaceDtor(std::ofstream& stream,
-                                             const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_DTOR, "##",
-      GetInterfaceIdWithNamespace(inf));
+std::string CProxyHeaderGen::GenMethodParams(const Interface& inf,
+    const Declaration& decl) {
+  std::string params;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, inf) +
+        p->GetID();
+  }
+
+  return params;
 }
 
-void CProxyHeaderGen::GenInterfaceConnectSync(std::ofstream& stream,
-                                              const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CONNECT_SYNC, "##",
-      GetInterfaceIdWithNamespace(inf));
+// @see #CB_INTERFACE_METHOD_BASE
+void CProxyHeaderGen::GenInterfaceMethodBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_BASE, "<RETURN_TYPE>",
+      GetReturnTypeString(decl.GetType()));
+  code = ReplaceAll(code, "<PREFIX>", GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<METHOD_NAME>", decl.GetID());
+  code = ReplaceAll(code, "<METHOD_PARAMS>", GenMethodParams(inf, decl));
+
+  stream << SmartIndent(code);
 }
 
 }  // namespace tidl
index 8dfa891..6b57873 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
@@ -33,21 +33,22 @@ class CProxyHeaderGen : public CHeaderGeneratorBase {
   void OnFiniGen(std::ofstream& stream) override;
 
  private:
-  void GenInterfaces(std::ofstream& stream);
+  void GenInterfaceHandles(std::ofstream& stream);
+  void GenInterfaceHandle(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
 
- private:
+  void GenInterfaces(std::ofstream& stream);
   void GenInterface(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceMethods(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceCtor(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceConnect(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDtor(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceConnectSync(std::ofstream& stream, const Interface& inf);
 
- private:
-  void GenInterfaceDelegator(std::ofstream& stream, const std::string& id,
-                             const Declaration& decl);
+  void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+  void GenInterfaceBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethodBase(std::ofstream& stream, const Interface& info,
+      const Declaration& decl);
+
+  std::string GenDelegateParams(const Interface& inf, const Declaration& decl);
+  std::string GenMethodParams(const Interface& inf, const Declaration& decl);
 };
 
 }  // namespace tidl
index e6849e1..0bb1231 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_PROXY_HEADER_GEN_CB_H_
 #define IDLC_C_GEN_C_PROXY_HEADER_GEN_CB_H_
 
-const char CB_INTERFACE_DECL[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_HANDLE[] =
 R"__c_cb(
-typedef struct ##_s *rpc_port_proxy_##_h;
-
-typedef struct {
-    void (*connected)(rpc_port_proxy_##_h h, void *user_data);
-    void (*disconnected)(rpc_port_proxy_##_h h, void *user_data);
-    void (*rejected)(rpc_port_proxy_##_h h, void *user_data);
-} rpc_port_proxy_##_callback_s;
+/**
+ * @brief The <PREFIX>_<NAME> handle.
+ */
+typedef struct <PREFIX>_<NAME>_s *<PREFIX>_<NAME>_h;
 )__c_cb";
 
-const char CB_INTERFACE_CTOR[] =
+constexpr const char CB_INTERFACE_DELEGATE_HANDLE[] =
 R"__c_cb(
-int rpc_port_proxy_##_create(const char *stub_appid,
-        rpc_port_proxy_##_callback_s *callback, void *user_data,
-        rpc_port_proxy_##_h *h);
+/**
+ * @brief The <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ */
+typedef struct <PREFIX>_<NAME>_<DELEGATE_NAME>_s *<PREFIX>_<NAME>_<DELEGATE_NAME>_h;
 )__c_cb";
 
-const char CB_INTERFACE_CONNECT[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate.
+ * <DELEGATE_PARAMS> The parameters of the callback function.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BASE[] =
 R"__c_cb(
-int rpc_port_proxy_##_connect(rpc_port_proxy_##_h h);
-)__c_cb";
+/**
+ * @brief Called when the event is received.
+ *
+ * @param[in] user_data The user data passed from the callback registration function
+ * @param[in] ...
+ *
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_create()
+ */
+typedef void (*<PREFIX>_<NAME>_<DELEGATE_NAME>_cb)(void *user_data<DELEGATE_PARAMS>);
 
-const char CB_INTERFACE_DTOR[] =
-R"__c_cb(
-int rpc_port_proxy_##_destroy(rpc_port_proxy_##_h h);
-)__c_cb";
+/**
+ * @brief Creates a <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[out] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memorya
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy()
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_dispose()
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_set_callback()
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_set_once()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_create(<PREFIX>_<NAME>_<DELEGATE_NAME>_h *h);
 
-const char CB_INTERFACE_METHODS[] =
-R"__c_cb(
-$$rpc_port_proxy_##_invoke_$$(rpc_port_proxy_##_h h$$);
-)__c_cb";
+/**
+ * @brief Destroys the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_create()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h);
 
-const char CB_INTERFACE_DELEGATOR[] =
-R"__c_cb(
-typedef $$(*$$)($$);
-)__c_cb";
+/**
+ * @brief Creates and returns a copy of the given <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @remarks A new created <PREFIX>_<NAME>_<DELEGATE_NAME> should be released using
+ *          the <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy() if it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] clone If successful, a new created <PREFIX>_<NAME>_<DELEGATE_NAME> handle will be returned
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_clone(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, <PREFIX>_<NAME>_<DELEGATE_NAME>_h *clone);
 
-const char CB_DELEGATE_CTOR[] =
-R"__c_cb(
-rpc_port_##_h rpc_port_##_create(## callback, bool once, void *user_data);
-)__c_cb";
+/**
+ * @brief Sets the callback function to the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_set_callback(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, <PREFIX>_<NAME>_<DELEGATE_NAME>_cb callback, void *user_data);
 
-const char CB_DELEGATE_DISPOSER[] =
-R"__c_cb(
-int rpc_port_proxy_##_dispose(rpc_port_proxy_$$_h proxy, rpc_port_##_h delegate);
+/**
+ * @brief Set the once flag to the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ * @details If the once flag is 'true', the delegate handle will be deleted after invocation.
+ *          If the @a h handle is not used using the method, the handle should be released using
+ *          the <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy() when it's no longer needed.
+ *          If you don't want the delegate callback function to be called after it's used using the method,
+ *          you should release the handle using the <PREFIX>_<NAME>_<DELEGATE_NAME>_dispose().
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[in] once The flag if it's true, the delegate will be deleted after invocation
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_set_once(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, bool once);
+
+/**
+ * @brief Gets the ID of the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] id The ID
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *id);
+
+/**
+ * @brief Gets the sequence ID of the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] seq_id The Sequence ID
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_seq_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *seq_id);
+
+/**
+ * @brief Checks whether the delegate is for one-time or not.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] once The flag, it's true, the handle is for one-time
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_is_once(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, bool *once);
+
+/**
+ * @brief Gets the tag from the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @remarks The @a tag should be released using free().
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] tag The tag
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_tag(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, char **tag);
+
+/**
+ * @brief Disposes the <PREFIX>_<NAME>_<DELEGATE_NAME> handle from the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] proxy The <PREFIX>_<NAME> handle
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_create()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_dispose(<PREFIX>_<NAME>_h proxy, <PREFIX>_<NAME>_<DELEGATE_NAME>_h h);
 )__c_cb";
 
-const char CB_DELEGATE_DTOR[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_BASE[] =
 R"__c_cb(
-int rpc_port_##_destroy(rpc_port_##_h delegate);
+/**
+ * @brief Called when the proxy is connected.
+ * @details The callback function is called when the proxy is connected to the stub.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] user_data The user data passed from the registeration function
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_connected_cb)(<PREFIX>_<NAME>_h h, void *user_data);
+
+/**
+ * @brief Called when the proxy is disconnected.
+ * @details The callback function is called when the proxy is disconnected from the stub.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] user_data The user data passed from the registeration function
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_disconnected_cb)(<PREFIX>_<NAME>_h h, void *user_data);
+
+/**
+ * @brief Called when the proxy is rejected.
+ * @details The callback function is called when the proxy is rejected to connect to the stub.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] user_data The user data passed from the registeration function
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_rejected_cb)(<PREFIX>_<NAME>_h h, void *user_data);
+
+/**
+ * @brief The structure type containing the set of callback functions for handling proxy events.
+ * @details It is one of the input parameters of the <PREFIX>_<NAME>_create() function.
+ *
+ * @see <PREFIX>_<NAME>_connected_cb
+ * @see <PREFIX>_<NAME>_disconnected_cb
+ * @see <PREFIX>_<NAME>_rejected_cb
+ */
+typedef struct {
+  <PREFIX>_<NAME>_connected_cb connected;  /**< This callback function is called when the proxy is connected to the stub. */
+  <PREFIX>_<NAME>_disconnected_cb disconnected;  /**< This callback function is called when the proxy is disconnected from the stub. */
+  <PREFIX>_<NAME>_rejected_cb rejected;  /**< This callback function is called when the proxy is rejected to connect to the stub. */
+} <PREFIX>_<NAME>_callback_s;
+
+/**
+ * @brief Creates a <PREFIX>_<NAME> handle.
+ * @remarks The @a h handle should be released using
+ *          the <PREFIX>_<NAME>_destroy() if it's no longer needed.
+ *
+ * @param[in] stub_appid The application ID of the stub
+ * @param[in] callback The set of callback functions to handle proxy events
+ * @param[in] user_data The user data to be passed to the callback function
+ * @param[out] h The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_destroy()
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+int <PREFIX>_<NAME>_create(const char *stub_appid, <PREFIX>_<NAME>_callback_s *callback, void *user_data, <PREFIX>_<NAME>_h *h);
+
+/**
+ * @brief Destroys the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_create()
+ */
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h);
+
+/**
+ * @brief Connects to the stub.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_IO_ERROR I/O error
+ * @retval #RPC_PORT_ERROR_PERMISSION_DENIED Permission denied
+ */
+int <PREFIX>_<NAME>_connect(<PREFIX>_<NAME>_h h);
+
+/**
+ * @brief Connects to the stub synchronously.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_IO_ERROR I/O error
+ * @retval #RPC_PORT_ERROR_PERMISSION_DENIED Permission denied
+ */
+int <PREFIX>_<NAME>_connect_sync(<PREFIX>_<NAME>_h h);
 )__c_cb";
 
-const char CB_INTERFACE_CONNECT_SYNC[] =
+/**
+ * <RETURN_TYPE> The type of the return value.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The of the interface.
+ * <METHOD_NAME> The name of the method.
+ * <METHOD_PARAMS> The parameters of the method.
+ */
+constexpr const char CB_INTERFACE_METHOD_BASE[] =
 R"__c_cb(
-int rpc_port_proxy_##_connect_sync(rpc_port_proxy_##_h h);
+/**
+ * @brief Calls the <METHOD_NAME>() method.
+ * @details The return value and args are decided by the interface declaration.
+ *          You can get the result using get_last_result().
+ *          Before returning the function, the function sets the result using set_last_result().
+ * @remarks The specific error code can be obtained using the get_last_result() function. Error codes are described in Exception section.
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] ...
+ * @exception #RPC_PORT_ERROR_NONE Successful
+ * @exception #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @exception #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception #RPC_PORT_ERROR_IO_ERROR I/O error
+ */
+<RETURN_TYPE><PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>);
 )__c_cb";
 
 #endif  // IDLC_C_GEN_C_PROXY_HEADER_GEN_CB_H_
index 68c4a0a..12355e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
  * limitations under the License.
  */
 
-#include "idlc/gen/c_stub_body_gen.h"
+#include <algorithm>
 
-namespace {
+#include "idlc/gen/c_stub_body_gen.h"
 #include "idlc/gen/c_stub_body_gen_cb.h"
-}
 
 namespace tidl {
 
 CStubBodyGen::CStubBodyGen(std::shared_ptr<Document> doc,
     std::shared_ptr<Options> options)
-    : CBodyGeneratorBase(doc), options_(options) {}
+    : CBodyGeneratorBase(doc), options_(options) {
+}
 
 void CStubBodyGen::OnInitGen(std::ofstream& stream) {
   GenVersion(stream);
@@ -33,601 +33,639 @@ void CStubBodyGen::OnInitGen(std::ofstream& stream) {
   GenIncludeHeader(stream);
   GenLogTag(stream, std::string("RPC_PORT_STUB"));
   GenLogDefinition(stream);
-  GenTypedefStubMethod(stream);
+  GenBaseDefinition(stream);
+  GenThreadEnableDefinition(stream);
+  GenInterfaceMethodHandlerType(stream);
+  GenInterfaceEnums(stream);
+  GenStructureDefs(stream);
+  GenInterfaceDefs(stream);
+  GenPrivateSharingListSet(stream);
   GenStructures(stream);
   GenInterfaces(stream);
 }
 
-void CStubBodyGen::OnFiniGen(std::ofstream& stream) {}
+void CStubBodyGen::OnFiniGen(std::ofstream& stream) {
+}
 
-void CStubBodyGen::GenInterfaces(std::ofstream& stream) {
-  for (auto& i : GetDocument().GetBlocks()) {
-    if (i->GetType() != Block::TYPE_INTERFACE)
+// @see #CB_THREAD_ENABLE_DEF
+void CStubBodyGen::GenThreadEnableDefinition(std::ofstream& stream) {
+  if (!options_->IsThreadEnabled())
+    return;
+
+  stream << std::string(CB_THREAD_ENABLE_DEF);
+}
+
+// @see #CB_INTERFACE_METHOD_HANDLER_TYPE
+void CStubBodyGen::GenInterfaceMethodHandlerType(std::ofstream& stream) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_HANDLER_TYPE, "<PREFIX>",
+      GetHandlePrefix());
+
+  stream << SmartIndent(code);
+}
+
+void CStubBodyGen::GenInterfaceEnums(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
       continue;
 
-    const Interface &inf = static_cast<const Interface&>(*i);
-    GenInterface(stream, inf);
+    auto& inf = static_cast<const Interface&>(*b);
+    GenInterfaceEnum(stream, inf);
   }
 }
 
-void CStubBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) {
-  GenInterfaceEnumerations(stream, inf);
-  GenInterfaceGlobalVariables(stream, inf);
-  GenInterfaceContext(stream, inf);
-  GenInterfaceDelegators(stream, inf);
-  GenInterfaceMethods(stream, inf);
-  GenInterfaceMethodTable(stream, inf);
-  GenInterfaceOnConnectedEventCB(stream, inf);
-  GenInterfaceOnDisconnectedEventCB(stream, inf);
-  GenInterfaceOnReceivedEventCB(stream, inf);
-  GenInterfaceAddPrivileges(stream, inf);
-  GenInterfaceRegister(stream, inf);
-  GenInterfaceUnregister(stream, inf);
-  GenInterfaceClientNumberGetter(stream, inf);
-}
-
-void CStubBodyGen::GenInterfaceMethods(std::ofstream& stream,
-                                       const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+void CStubBodyGen::GenInterfaceEnum(std::ofstream& stream,
+    const Interface& inf) {
+  GenInterfaceMethodEnumBase(stream, inf);
+  GenInterfaceDelegateEnumBase(stream, inf);
+}
+
+// @see #CB_INTERFACE_METHOD_ENUM
+std::string CStubBodyGen::GenMethodEnums(const Interface& inf) {
+  std::string method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM,
+      "<UPPERCASE_PREFIX>", GetHandlePrefix());
+  method_enum = ReplaceAll(method_enum, "<UPPERCASE_NAME>", inf.GetID());
+  method_enum = ReplaceAll(method_enum, "<UPPERCASE_METHOD_NAME>", "RESULT_");
+  std::string method_enums = RemoveLine(method_enum);
+
+  method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, "<UPPERCASE_PREFIX>",
+      GetHandlePrefix());
+  method_enum = ReplaceAll(method_enum, "<UPPERCASE_NAME>", inf.GetID());
+  method_enum = ReplaceAll(method_enum, "<UPPERCASE_METHOD_NAME>", "CALLBACK_");
+  method_enums += RemoveLine(method_enum);
+
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
       continue;
 
-    stream << SmartIndent(GenTemplateString(CB_INTERFACE_METHOD,
-          [&]()->std::string {
-            return GetInterfaceIdWithNamespace(inf);
-          },
-          [&]()->std::string {
-            return i->GetID();
-          },
-          [&]()->std::string {
-            return GetInterfaceIdWithNamespace(inf);
-          },
-          [&]()->std::string {
-            return GetInterfaceIdWithNamespace(inf);
-          },
-          [&]()->std::string {
-            return GetMethodString(inf, *i);
-          }));
+    method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, "<UPPERCASE_PREFIX>",
+        GetHandlePrefix());
+    method_enum = ReplaceAll(method_enum, "<UPPERCASE_NAME>", inf.GetID());
+    method_enum = ReplaceAll(method_enum, "<UPPERCASE_METHOD_NAME>",
+        d->GetID());
+
+    method_enums += RemoveLine(method_enum);
   }
+  std::transform(method_enums.begin(), method_enums.end(), method_enums.begin(),
+      ::toupper);
+
+  return method_enums;
 }
 
-void CStubBodyGen::GenInterfaceMethodTable(std::ofstream& stream,
-                                           const Interface& inf) {
-  std::string str;
-  int cnt = 0;
+// @see #CB_INTERFACE_METHOD_ENUM_BASE
+void CStubBodyGen::GenInterfaceMethodEnumBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<METHOD_ENUMS>", GenMethodEnums(inf));
+
+  stream << SmartIndent(code);
+}
 
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+// @see #CB_INTERFACE_DELEGATE_ENUM
+std::string CStubBodyGen::GenDelegateEnums(const Interface& inf) {
+  unsigned int num = 1;
+  std::string method_enums;
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
       continue;
-    str += GenTemplateString(CB_INTERFACE_METHOD_FORMAT,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf) + "_METHOD_" + i->GetID();
-        },
-        [&]()->std::string {
-          return "__" + GetInterfaceIdWithNamespace(inf) + "_method_"
-              + i->GetID();
-        });
-    cnt++;
+
+    std::string method_enum = ReplaceAll(CB_INTERFACE_DELEGATE_ENUM,
+        "<UPPERCASE_PREFIX>", GetHandlePrefix());
+    method_enum = ReplaceAll(method_enum, "<UPPERCASE_NAME>", inf.GetID());
+    method_enum = ReplaceAll(method_enum, "<UPPERCASE_DELEGATE_NAME>",
+        d->GetID());
+    method_enum = ReplaceAll(method_enum, "<NUMBER>", std::to_string(num++));
+
+    method_enums += RemoveLine(method_enum);
   }
+  std::transform(method_enums.begin(), method_enums.end(), method_enums.begin(),
+      ::toupper);
 
-  if (cnt == 0)
-    return;
+  return method_enums;
+}
+
+// @see #CB_INTERFACE_DELEGATE_ENUM_BASE
+void CStubBodyGen::GenInterfaceDelegateEnumBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_ENUM_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_ENUMS>", GenDelegateEnums(inf));
+
+  stream << SmartIndent(code);
+}
+
+void CStubBodyGen::GenInterfaceDefs(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
 
-  stream << NLine(1);
-  stream << SmartIndent(GenTemplateString(CB_INTERFACE_METHOD_TABLE,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          return str;
-        }));
-}
-
-void CStubBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream,
-                                                  const Interface& inf) {
-  if (options_->IsThreadEnabled()) {
-    stream << SmartIndent(
-      ReplaceAll(CB_INTERFACE_THREAD_METHODS, "##",
-          GetInterfaceIdWithNamespace(inf)));
+    auto& inf = static_cast<const Interface&>(*b);
+    GenInterfaceDef(stream, inf);
   }
+}
 
-  stream << SmartIndent(
-      ReplaceAll(CB_INTERFACE_ON_CONNECTED, "##",
-          GetInterfaceIdWithNamespace(inf)));
+void CStubBodyGen::GenInterfaceDef(std::ofstream& stream,
+    const Interface& inf) {
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenInterfaceDelegateDef(stream, inf, *d);
+  }
+
+  GenInterfaceContextDef(stream, inf);
+  GenInterfaceBaseDef(stream, inf);
 }
 
-void CStubBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
-                                                     const Interface& inf) {
-  stream << SmartIndent(
-      ReplaceAll(CB_INTERFACE_ON_DISCONNECTED, "##",
-          GetInterfaceIdWithNamespace(inf)));
+// @see #CB_INTERFACE_DELEGATE_DEF
+void CStubBodyGen::GenInterfaceDelegateDef(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+
+  stream << SmartIndent(code);
 }
 
-void CStubBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream,
-                                                 const Interface& inf) {
-  if (options_->IsThreadEnabled()) {
-    stream << SmartIndent(
-      ReplaceAll(CB_INTERFACE_THREAD_ON_RECEIVED, "##",
-          GetInterfaceIdWithNamespace(inf)));
-  } else {
-    stream << SmartIndent(
-        ReplaceAll(CB_INTERFACE_ON_RECEIVED, "##",
-            GetInterfaceIdWithNamespace(inf)));
+// @see #CB_INTERFACE_CONTEXT_DEF
+void CStubBodyGen::GenInterfaceContextDef(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_BASE_DEF
+void CStubBodyGen::GenInterfaceBaseDef(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+
+  stream << SmartIndent(code);
+}
+
+void CStubBodyGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    const Interface &inf = static_cast<const Interface&>(*i);
+    GenInterface(stream, inf);
   }
 }
 
-void CStubBodyGen::GenInterfaceRegister(std::ofstream& stream,
-                                        const Interface& inf) {
-  std::string r_str = ReplaceAll(CB_INTERFACE_REGISTER, "##",
-      GetInterfaceIdWithNamespace(inf));
-
-  stream << SmartIndent(GenTemplateString(r_str,
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return CB_INTERFACE_THREAD_CREATE;
-          return "";
-        }));
-}
-
-void CStubBodyGen::GenInterfaceUnregister(std::ofstream& stream,
-                                          const Interface& inf) {
-  std::string r_str = ReplaceAll(CB_INTERFACE_UNREGISTER, "##",
-      GetInterfaceIdWithNamespace(inf));
-
-  stream << SmartIndent(GenTemplateString(r_str,
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return "job_h job;";
-          return "";
-        },
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return CB_INTERFACE_THREAD_DESTROY;
-          return "";
-        }));
-}
-
-void CStubBodyGen::GenInterfaceGlobalVariables(std::ofstream& stream,
-                                               const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_GLOBALS, "##",
-      GetInterfaceIdWithNamespace(inf)));
-}
-
-std::string CStubBodyGen::GetMethodString(const Interface& inf,
-                                          const Declaration& decl) {
-  std::string str;
-  const char port_setter[] = "rpc_port_$$_set_port($$, callback_port);\n";
-  const char setter[] = "$$($$, $$);\n";
-  const char do_while_block[] =
-      "do {\n" \
-      "    rpc_port_parcel_h result;\n" \
-      "\n" \
-      "    rpc_port_parcel_create(&result);\n" \
-      "    rpc_port_parcel_write_int32(result, $$_METHOD_Result);\n" \
-      "$$" \
-      "    r = rpc_port_parcel_send(result, port);\n" \
-      "    rpc_port_parcel_destroy(result);\n" \
-      "} while (0);\n";
-  const char ternary_operation[] = "## ? ## : \"\"";
-  int cnt = 0;
-  for (auto& i : decl.GetParameters().GetParams()) {
-    if (IsDelegateType(inf, i->GetParameterType().GetBaseType())) {
-      str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" +
-          i->GetParameterType().GetBaseType().ToString() + "_h " +
-          i->GetID() + " = NULL;" + NLine(1);
-    } else if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
-               i->GetParameterType().GetBaseType().ToString() == "list" ||
-               i->GetParameterType().GetBaseType().ToString() == "array") {
-      str += GetReturnTypeString(i->GetParameterType().GetBaseType()) +
-          i->GetID() + " = NULL;" + NLine(1);
-    } else {
-      str += GetReturnTypeString(i->GetParameterType().GetBaseType()) +
-          i->GetID() + ";" + NLine(1);
-    }
-    if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN)
-      cnt++;
+void CStubBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) {
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenInterfaceDelegateBase(stream, inf, *d);
   }
-  str += NLine(1);
 
-  for (auto& i : decl.GetParameters().GetParams()) {
-    if (i->GetParameterType().GetDirection() != ParameterType::Direction::IN)
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
       continue;
 
-    if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
-        i->GetParameterType().GetBaseType().ToString() == "list" ||
-        i->GetParameterType().GetBaseType().ToString() == "array") {
-      if (IsDelegateType(inf, i->GetParameterType().GetBaseType())) {
-        str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" +
-            i->GetParameterType().GetBaseType().ToString() +
-            "_create(&" + i->GetID() + ");" + NLine(1);
-        str += "\nif (!" + i->GetID() + ") {\n";
-        str += "    _E(\"Failed to create handle\");\n";
-        str += "    return -1;\n";
-        str += "}\n\n";
-        str += GenTemplateString(port_setter,
-            [&]()->std::string {
-              return GetInterfaceIdWithNamespace(inf) + "_" +
-                  i->GetParameterType().GetBaseType().ToString();
-            },
-            [&]()->std::string {
-              return i->GetID();
-            });
-      } else {
-         str += GetConstructorString(i->GetParameterType().GetBaseType(),
-          i->GetID());
-      }
-    }
+    GenInterfaceMethodHandlerBase(stream, inf, *d);
+  }
+
+  GenInterfaceMethodTable(stream, inf);
+  GenInterfaceContextBase(stream, inf);
+  GenInterfaceBase(stream, inf);
+}
+
+// @see #CB_INTERFACE_CONTEXT_BASE
+void CStubBodyGen::GenInterfaceContextBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
 
-    str += GenTemplateString(setter,
-          [&]()->std::string {
-            return GetParcelReadFunctionString(
-                i->GetParameterType().GetBaseType(), true);
-          },
-          [&]()->std::string {
-            return "parcel";
-          },
-          [&]()->std::string {
-            if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
-                i->GetParameterType().GetBaseType().ToString() == "list" ||
-                i->GetParameterType().GetBaseType().ToString() == "array")
-              return "&" + i->GetID() + "->parcelable, " + i->GetID();
-            return "&" + i->GetID();
-          });
+  stream << SmartIndent(code);
+}
+
+std::string CStubBodyGen::GenDelegateParams(const Interface& inf,
+    const Declaration& decl) {
+  std::string params;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, inf) +
+        p->GetID();
   }
 
-  if (cnt > 0)
-    str += NLine(1);
+  return params;
+}
+
+std::string CStubBodyGen::GenDelegateParamsCheck(const Interface& inf,
+    const Declaration& decl) {
+  std::string params_check;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array" ||
+        type.ToString() == "bundle" ||
+        type.ToString() == "string" ||
+        type.ToString() == "file")
+      params_check += " || " + p->GetID() + " == nullptr";
+  }
 
-  if (decl.GetMethodType() == Declaration::MethodType::SYNC &&
-      decl.GetType().ToString() != "void") {
-    str += GetReturnTypeString(decl.GetType()) + "ret = ";
+  return params_check;
+}
+
+// @see #CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_WRITE
+// @see #CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_WRITE
+// @see #CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE
+// @see #CB_INTERFACE_DELEGATE_BASE_PARCEL_WRITE
+std::string CStubBodyGen::GenDelegateParcelWrite(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    std::string parcel_write_code;
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_write_code = ReplaceAll(
+          CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_WRITE, "<ARG>",
+          p->GetID());
+      parcel_write_code += GetPrivateSharingString(type, inf, "h->port",
+          p->GetID());
+    } else if (type.ToString() == "bundle") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "file") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+      parcel_write_code += GetPrivateSharingString(type, inf, "h->port",
+          p->GetID());
+    } else {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE_PARCEL_WRITE,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_write_code = ReplaceAll(parcel_write_code, "<ARG>", p->GetID());
+    }
+
+    code += parcel_write_code;
   }
 
-  str += "context->callback." + decl.GetID() + "(context";
-  for (auto& i : decl.GetParameters().GetParams()) {
-    str += ", ";
-    if (i->GetParameterType().GetDirection() != ParameterType::Direction::IN)
-      str += "&" + i->GetID();
-    else
-      str += i->GetID();
+  return RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_DELEGATE_BASE
+void CStubBodyGen::GenInterfaceDelegateBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+  code = ReplaceAll(code, "<DELEGATE_PARAMS>", GenDelegateParams(inf, decl));
+  code = ReplaceAll(code, "<DELEGATE_PARAMS_CHECK>",
+      GenDelegateParamsCheck(inf, decl));
+
+  std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() +
+      "_DELEGATE_" + decl.GetID();
+  std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(),
+      ::toupper);
+  code = ReplaceAll(code, "<DELEGATE_ENUM_VALUE>", enum_value);
+  code = ReplaceAll(code, "<DELEGATE_PARCEL_WRITE>",
+      GenDelegateParcelWrite(inf, decl));
+
+  stream << SmartIndent(code);
+}
+
+std::string CStubBodyGen::GenMethodHandlerArgsDecl(const Interface& inf,
+    const Declaration& decl) {
+  std::string args_decl;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    args_decl += GetArgTypeString(type, inf) + p->GetID() + " = " +
+        GetErrorValue(type) + ";" + NLine(1);
   }
-  str += ", context->user_data);" + NLine(1);
+
   if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
-    str += GenTemplateString(do_while_block,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          std::string s;
-          for (auto& i : decl.GetParameters().GetParams()) {
-            if (i->GetParameterType().GetDirection() ==
-                ParameterType::Direction::IN)
-              continue;
-            s += GenTemplateString(setter,
-                [&]()->std::string {
-                  return GetParcelWriteFunctionString(
-                      i->GetParameterType().GetBaseType(), true);
-                },
-                [&]()->std::string {
-                  return "result";
-                },
-                [&]()->std::string {
-                  auto& t = i->GetParameterType().GetBaseType();
-                  if (t.IsUserDefinedType() || t.ToString() == "list" ||
-                      t.ToString() == "array")
-                    return "&" + i->GetID() + "->parcelable, " + i->GetID();
-                  else if (t.ToString() == "string" || t.ToString() == "file")
-                    return ReplaceAll(ternary_operation, "##", i->GetID());
-                  return i->GetID();
-                });
-          }
-          if (decl.GetType().ToString() != "void") {
-            s += GenTemplateString(setter,
-                [&]()->std::string {
-                  return GetParcelWriteFunctionString(decl.GetType(), true);
-                },
-                [&]()->std::string {
-                  return "result";
-                },
-                [&]()->std::string {
-                  if (decl.GetType().IsUserDefinedType() ||
-                      decl.GetType().ToString() == "list" ||
-                      decl.GetType().ToString() == "array")
-                    return "&ret->parcelable, ret";
-                  else if (decl.GetType().ToString() == "string" ||
-                      decl.GetType().ToString() == "file")
-                    return ReplaceAll(ternary_operation, "##", "ret");
-                  return "ret";
-                });
-          }
-          return s;
-        });
-    }
+    args_decl += "rpc_port_parcel_h parcel_;" + NLine(1);
+    args_decl += GetArgTypeString(decl.GetType(), inf) + "res_ = " +
+        GetErrorValue(decl.GetType()) + ";" + NLine(1);
+  }
 
-  for (auto& i : decl.GetParameters().GetParams()) {
-    str += NLine(1);
-    if (IsDelegateType(inf, i->GetParameterType().GetBaseType())) {
-      str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" +
-          i->GetParameterType().GetBaseType().ToString() +
-          "_destroy(" + i->GetID() + ");";
+  return args_decl;
+}
+
+// @see #CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_STRING_PARCEL_READ
+// @see #CB_INTERFACE_METHOD_BASE_PARCEL_READ
+std::string CStubBodyGen::GenMethodHandlerParcelRead(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    std::string parcel_read_code;
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type)) {
+      parcel_read_code = ReplaceAll(
+          CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ, "<PREFIX>",
+          GetHandlePrefix());
+      parcel_read_code = ReplaceAll(parcel_read_code, "<NAME>",
+          GetFullNameFromType(type, inf));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ARG>", p->GetID());
+    } else if (type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_read_code = ReplaceAll(
+          CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ, "<PREFIX>",
+          GetHandlePrefix());
+      parcel_read_code = ReplaceAll(parcel_read_code, "<NAME>",
+          GetFullNameFromType(type, inf));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ARG>", p->GetID());
+    } else if (type.ToString() == "bundle") {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ,
+          "<ARG>", p->GetID());
     } else {
-      str += GetDestructorString(i->GetParameterType().GetBaseType(),
-          i->GetID());
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ARG>", p->GetID());
     }
-  }
 
-  str += GetDestructorString(decl.GetType(), "ret");
+    code += parcel_read_code;
+  }
 
-  return str;
+  return RemoveLine(code);
 }
 
-std::string CStubBodyGen::GetAddPrivilegeString(const std::string& id,
-                                                const Attribute& attr) {
-  std::string str;
+// @see #CB_INTERFACE_METHOD_CALLBACK_INVOKE
+std::string CStubBodyGen::GenMethodHandlerCallbackInvoke(
+    const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_INVOKE,
+      "<METHOD_NAME>", decl.GetID());
 
-  str += GenTemplateString(CB_INTERFACE_PRIVILEGE_BLOCK,
-      [&]()->std::string {
-        return "rpc_port_stub_add_privilege(__" + id +
-            "_stub, \"" + attr.GetValue() + "\")";
-      },
-      [&]()->std::string {
-        return attr.GetValue();
-      });
-  return str;
-}
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC)
+    code = ReplaceAll(code, "<RES_SET>", "res_ = ");
+  else
+    code = ReplaceAll(code, "<RES_SET>", "");
 
-std::string CStubBodyGen::GetTrustedModeString(const std::string& id,
-                                               const Attribute& attr) {
-  std::string str;
+  std::string args;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    args += ", ";
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::IN)
+      args += "&";
 
-  str += GenTemplateString(CB_INTERFACE_TRUSTED_MODE_BLOCK,
-      [&]()->std::string {
-        return "rpc_port_stub_set_trusted(__" + id +
-            "_stub, " + attr.GetValue() + ")";
-      },
-      [&]()->std::string {
-        return attr.GetValue();
-      });
-  return str;
-}
+    args += p->GetID();
+  }
+  code = ReplaceAll(code, "<METHOD_ARGS>", args);
+
+  return RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_METHOD_PARCEL_WRITE_PRE
+// @see #CB_INTERFACE_METHOD_PARCEL_WRITE_POST
+// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_STRING_PARCEL_WRITE
+// @see #CB_INTERFACE_METHOD_BASE_PARCEL_WRITE
+std::string CStubBodyGen::GenMethodHandlerParcelWrite(const Interface& inf,
+    const Declaration& decl) {
+  std::string code;
+  if (decl.GetMethodType() != Declaration::MethodType::SYNC)
+    return code;
+
+  std::string name = inf.GetID();
+  std::transform(name.begin(), name.end(), name.begin(), ::toupper);
+  code = ReplaceAll(CB_INTERFACE_METHOD_PARCEL_WRITE_PRE, "<UPPERCASE_NAME>",
+      name);
+
+  std::string parcel_write_code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() == ParameterType::Direction::IN)
+      continue;
+
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      parcel_write_code = ReplaceAll(
+          CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "<ARG>",
+          p->GetID());
+      parcel_write_code += GetPrivateSharingString(type, inf, "port",
+          p->GetID());
+    } else if (type.ToString() == "bundle") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "file") {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE,
+          "<ARG>", p->GetID());
+      parcel_write_code += GetPrivateSharingString(type, inf, "port",
+          p->GetID());
+    } else {
+      parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_write_code = ReplaceAll(parcel_write_code, "<ARG>", p->GetID());
+    }
+
+    code += parcel_write_code;
+  }
 
-void CStubBodyGen::GenInterfaceDelegators(std::ofstream& stream,
-                                          const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+  auto& type = decl.GetType();
+  if (IsDelegateType(inf, type) ||
+      type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    parcel_write_code = ReplaceAll(
+        CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "<ARG>", "res_");
+    parcel_write_code += GetPrivateSharingString(type, inf, "port", "res_");
+  } else if (type.ToString() == "bundle") {
+    parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE,
+        "<ARG>", "res_");
+  } else if (type.ToString() == "string") {
+    parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE,
+        "<ARG>", "res_");
+  } else if (type.ToString() == "file") {
+    parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE,
+        "<ARG>", "res_");
+    parcel_write_code += GetPrivateSharingString(type, inf, "port", "res_");
+  } else {
+    parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE,
+        "<PARCEL_TYPE>", GetParcelType(type));
+    parcel_write_code = ReplaceAll(parcel_write_code, "<ARG>", "res_");
+  }
+
+  code += parcel_write_code;
+  code += std::string(CB_INTERFACE_METHOD_PARCEL_WRITE_POST);
+
+  return RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_METHOD_USER_DEFINED_FREE
+// @see #CB_INTERFACE_METHOD_BUNDLE_FREE
+// @see #CB_INTERFACE_METHOD_STRING_FREE
+std::string CStubBodyGen::GenMethodHandlerArgsFree(const Interface& inf,
+    const Declaration& decl) {
+  std::string free_code;
+  std::string code;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_FREE,
+          "<PREFIX>", GetHandlePrefix());
+      free_code = ReplaceAll(free_code, "<NAME>",
+          GetFullNameFromType(type, inf));
+      free_code = ReplaceAll(free_code, "<ARG>", p->GetID());
+    } else if (type.ToString() == "bundle") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_FREE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_FREE,
+          "<ARG>", p->GetID());
+    } else {
+      free_code.clear();
+    }
+
+    code += free_code;
+  }
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
+    auto& type = decl.GetType();
+    if (IsDelegateType(inf, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_FREE,
+          "<PREFIX>", GetHandlePrefix());
+      free_code = ReplaceAll(free_code, "<NAME>",
+          GetFullNameFromType(type, inf));
+      free_code = ReplaceAll(free_code, "<ARG>", "res_");
+    } else if (type.ToString() == "bundle") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_FREE,
+          "<ARG>", "res_");
+    } else if (type.ToString() == "string" || type.ToString() == "file") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_FREE,
+          "<ARG>", "res_");
+    } else {
+      free_code.clear();
+    }
+
+    code += free_code;
+  }
+
+  return RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_METHOD_HANDLER_BASE
+void CStubBodyGen::GenInterfaceMethodHandlerBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_HANDLER_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<METHOD_NAME>", decl.GetID());
+  code = ReplaceAll(code, "<METHOD_HANDLER_ARGS_DECL>",
+      GenMethodHandlerArgsDecl(inf, decl));
+  code = ReplaceAll(code, "<METHOD_HANDLER_PARCEL_READ>",
+      GenMethodHandlerParcelRead(inf, decl));
+  code = ReplaceAll(code, "<METHOD_HANDLER_CALLBACK_INVOKE>",
+      GenMethodHandlerCallbackInvoke(decl));
+  code = ReplaceAll(code, "<METHOD_HANDLER_PARCEL_WRITE>",
+      GenMethodHandlerParcelWrite(inf, decl));
+  code = ReplaceAll(code, "<METHOD_HANDLER_ARGS_FREE>",
+      GenMethodHandlerArgsFree(inf, decl));
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_HANDLER
+std::string CStubBodyGen::GenMethodHandlers(const Interface& inf) {
+  std::string code;
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
       continue;
-    GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i);
+
+    std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() +
+      "_METHOD_" + d->GetID();
+    std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(),
+        ::toupper);
+    std::string method_handler = ReplaceAll(CB_INTERFACE_METHOD_HANDLER,
+        "<ENUM_VALUE>", enum_value);
+    method_handler = ReplaceAll(method_handler, "<PREFIX>", GetHandlePrefix());
+    method_handler = ReplaceAll(method_handler, "<NAME>", inf.GetID());
+    method_handler = ReplaceAll(method_handler, "<METHOD_NAME>", d->GetID());
+
+    code += RemoveLine(method_handler);
   }
+
+  return code;
 }
 
-void CStubBodyGen::GenInterfaceDelegator(std::ofstream& stream,
-                                         const std::string& id,
-                                         const Declaration& decl) {
-  GenInterfaceDelegatorDeclaration(stream, id, decl);
-  GenInterfaceDelegatorSerializer(stream, id, decl);
-  GenInterfaceDelegatorDeserializer(stream, id, decl);
-  GenInterfaceDelegatorConstructor(stream, id, decl);
-  GenInterfaceDelegatorDestructor(stream, id, decl);
-  GenInterfaceDelegatorCloner(stream, id, decl);
-  GenInterfaceDelegatorInvoker(stream, id, decl);
-  GenInterfaceDelegatorPortSetter(stream, id, decl);
-}
-
-void CStubBodyGen::GenInterfaceDelegatorDeclaration(std::ofstream& stream,
-                                                    const std::string& id,
-                                                    const Declaration& decl) {
-  stream << SmartIndent(GenTemplateString(CB_INTERFACE_DELEGATOR_DECL,
-        [&]()->std::string {
-          return id + "_" + decl.GetID();
-        }));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorConstructor(std::ofstream& stream,
-                                                    const std::string& id,
-                                                    const Declaration& decl) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_INTERFACE_DELEGATOR_CTOR, "##", id + "_" + decl.GetID()),
-        [&]()->std::string {
-          return id;
-        },
-        [&]()->std::string {
-          return decl.GetID();
-        }));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorDestructor(std::ofstream& stream,
-                                                   const std::string& id,
-                                                   const Declaration& decl) {
-  stream << SmartIndent(
-      ReplaceAll(CB_INTERFACE_DELEGATOR_DTOR, "##", id + "_" + decl.GetID()));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorSerializer(std::ofstream& stream,
-                                                   const std::string& id,
-                                                   const Declaration& decl) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_DELEGATOR_SERIALIZER, "##", id + "_" + decl.GetID()));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorDeserializer(std::ofstream& stream,
-                                                     const std::string& id,
-                                                     const Declaration& decl) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_DELEGATOR_DESERIALIZER, "##", id + "_" + decl.GetID()));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorCloner(std::ofstream& stream,
-                                               const std::string& id,
-                                               const Declaration& decl) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_DELEGATOR_CLONER, "##", id + "_" + decl.GetID()));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorInvoker(std::ofstream& stream,
-                                                const std::string& id,
-                                                const Declaration& decl) {
-  const char parcel[] = "$$(parcel, $$);\n";
-  const char ternary_operation[] = "## ? ## : \"\"";
-  stream << SmartIndent(GenTemplateString(CB_INTERFACE_DELEGATOR_INVOKER,
-        [&]()->std::string {
-          return id + "_" + decl.GetID();
-        },
-        [&]()->std::string {
-          std::string str;
-          str += "rpc_port_" + id + "_" + decl.GetID() + "_h h";
-          for (auto& i : decl.GetParameters().GetParams()) {
-            str += ", ";
-            str += GetParamTypeString(i->GetParameterType().GetDirection(),
-                i->GetParameterType().GetBaseType()) + i->GetID();
-          }
-          return str;
-        },
-        [&]()->std::string {
-          return id;
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : decl.GetParameters().GetParams()) {
-            str += GenTemplateString(parcel,
-                [&]()->std::string {
-                  return GetParcelWriteFunctionString(
-                      i->GetParameterType().GetBaseType(), true);
-                },
-                [&]()->std::string {
-                  auto& t = i->GetParameterType().GetBaseType();
-                  if (t.IsUserDefinedType() || t.ToString() == "list" ||
-                      t.ToString() == "array")
-                    return "&" + i->GetID() + "->parcelable, " + i->GetID();
-                  else if (t.ToString() == "string" || t.ToString() == "file")
-                    return ReplaceAll(ternary_operation, "##", i->GetID());
-                  return i->GetID();
-                });
-          }
-          return str;
-        }));
-}
-
-void CStubBodyGen::GenInterfaceDelegatorPortSetter(std::ofstream& stream,
-                                                   const std::string& id,
-                                                   const Declaration& decl) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_DELEGATOR_PORT_SETTER, "##", id + "_" + decl.GetID()));
-}
-
-void CStubBodyGen::GenInterfaceContext(std::ofstream& stream,
-                                       const Interface& inf) {
-  GenInterfaceContextDeclaration(stream, inf);
-  GenInterfaceContextConstructor(stream, inf);
-  GenInterfaceContextDestructor(stream, inf);
-  GenInterfaceContextFinder(stream, inf);
-  GenInterfaceContextTagSetter(stream, inf);
-  GenInterfaceContextTagGetter(stream, inf);
-  GenInterfaceContextSenderGetter(stream, inf);
-}
-
-void CStubBodyGen::GenInterfaceContextDeclaration(std::ofstream& stream,
-                                                  const Interface& inf) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_INTERFACE_CONTEXT_DECL, "##",
-            GetInterfaceIdWithNamespace(inf)),
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return std::string(CB_INTERFACE_CONTEXT_DECL_THREAD_ELEM);
-          return "";
-        }));
-
-  if (options_->IsThreadEnabled()) {
-    stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_THREAD_FEATURE, "##", GetInterfaceIdWithNamespace(inf)));
+// @see #CB_INTERFACE_METHOD_TABLE
+void CStubBodyGen::GenInterfaceMethodTable(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_TABLE, "<NAME>",
+      inf.GetID());
+  code = ReplaceAll(code, "<METHOD_HANDLERS>", GenMethodHandlers(inf));
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_PRIVILEGE_ADD
+// @see #CB_INTERFACE_TRUSTED_SET
+std::string CStubBodyGen::GenAccessControlSet(const Interface& inf) {
+  std::string code;
+  for (auto& attr : inf.GetAttributes().GetAttrs()) {
+    if (attr->GetKey() == "privilege") {
+      std::string privilege_add = ReplaceAll(CB_INTERFACE_PRIVILEGE_ADD,
+          "<NAME>", inf.GetID());
+      privilege_add = ReplaceAll(privilege_add, "<PRIVILEGE>",
+          attr->GetValue());
+
+      code += privilege_add;
+    } else if (attr->GetKey() == "trusted" && attr->GetValue() == "true") {
+      std::string trusted_set = ReplaceAll(CB_INTERFACE_TRUSTED_SET,
+          "<NAME>", inf.GetID());
+
+      code += trusted_set;
+    }
   }
+
+  return RemoveLine(code);
 }
 
-void CStubBodyGen::GenInterfaceContextConstructor(std::ofstream& stream,
-                                                  const Interface& inf) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_INTERFACE_CONTEXT_CTOR, "##",
-            GetInterfaceIdWithNamespace(inf)),
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return std::string(CB_INTERFACE_CONTEXT_CTOR_THREAD_IMPL);
-          return "";
-        }));
-}
-
-void CStubBodyGen::GenInterfaceContextDestructor(std::ofstream& stream,
-                                                 const Interface& inf) {
-  stream << SmartIndent(GenTemplateString(
-        ReplaceAll(CB_INTERFACE_CONTEXT_DTOR, "##",
-            GetInterfaceIdWithNamespace(inf)),
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return std::string(CB_INTERFACE_CONTEXT_DTOR_THREAD_VARS);
-          return "";
-        },
-        [&]()->std::string {
-          if (options_->IsThreadEnabled())
-            return std::string(CB_INTERFACE_CONTEXT_DTOR_THREAD_IMPL);
-          return "";
-        }));
-}
-
-void CStubBodyGen::GenInterfaceContextFinder(std::ofstream& stream,
-                                             const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_CONTEXT_FINDER, "##", GetInterfaceIdWithNamespace(inf)));
-}
-
-void CStubBodyGen::GenInterfaceContextTagSetter(std::ofstream& stream,
-                                                const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_CONTEXT_TAG_SETTER, "##", GetInterfaceIdWithNamespace(inf)));
-}
-
-void CStubBodyGen::GenInterfaceContextTagGetter(std::ofstream& stream,
-                                                const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_CONTEXT_TAG_GETTER, "##", GetInterfaceIdWithNamespace(inf)));
-}
-
-void CStubBodyGen::GenInterfaceContextSenderGetter(std::ofstream& stream,
-                                                   const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(
-      CB_INTERFACE_CONTEXT_GET_SENDER, "##", GetInterfaceIdWithNamespace(inf)));
-}
-
-void CStubBodyGen::GenTypedefStubMethod(std::ofstream& stream) {
-  stream << CB_STUB_METHOD_TYPE;
-}
-
-void CStubBodyGen::GenInterfaceAddPrivileges(std::ofstream& stream,
-                                             const Interface& inf) {
-  stream << SmartIndent(GenTemplateString(CB_INTERFACE_ADD_PRIVILEGE,
-        [&]()->std::string {
-          return GetInterfaceIdWithNamespace(inf);
-        },
-        [&]()->std::string {
-          std::string str;
-          for (auto& a : inf.GetAttributes().GetAttrs()) {
-            if (a->GetKey() == "privilege") {
-              str += GetAddPrivilegeString(
-                  GetInterfaceIdWithNamespace(inf), *a);
-              str += NLine(1);
-            } else if (a->GetKey() == "trusted" && a->GetValue() == "true") {
-              str += GetTrustedModeString(GetInterfaceIdWithNamespace(inf), *a);
-              str += NLine(1);
-            }
-          }
-
-          if (!str.empty())
-            str = SmartIndent("int r;\n\n") + str;
-          return str;
-        }));
-}
-
-void CStubBodyGen::GenInterfaceClientNumberGetter(std::ofstream& stream,
-                                                  const Interface& inf) {
-  stream << SmartIndent(ReplaceAll(CB_INTERFACE_CLIENT_NUMBER_GETTER, "##",
-      GetInterfaceIdWithNamespace(inf)));
+// @see #CB_INTERFACE_BASE
+void CStubBodyGen::GenInterfaceBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<ACCESS_CONTROL_SET>", GenAccessControlSet(inf));
+
+  stream << SmartIndent(code);
 }
 
 }  // namespace tidl
index f787774..31b55db 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
@@ -35,77 +35,51 @@ class CStubBodyGen : public CBodyGeneratorBase {
   void OnFiniGen(std::ofstream& stream) override;
 
  private:
+  void GenThreadEnableDefinition(std::ofstream& stream);
+  void GenInterfaceMethodHandlerType(std::ofstream& stream);
+  void GenInterfaceEnums(std::ofstream& stream);
+  void GenInterfaceEnum(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethodEnumBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateEnumBase(std::ofstream& stream,
+      const Interface& inf);
+
+  void GenInterfaceDefs(std::ofstream& stream);
+  void GenInterfaceDef(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceContextDef(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateDef(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+  void GenInterfaceBaseDef(std::ofstream& stream, const Interface& inf);
+
   void GenInterfaces(std::ofstream& stream);
   void GenInterface(std::ofstream& stream, const Interface& inf);
-  void GenTypedefStubMethod(std::ofstream& stream);
-  void GenInterfaceMethods(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceContextBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+  void GenInterfaceMethodHandlerBase(std::ofstream& stream,
+      const Interface& inf, const Declaration& decl);
   void GenInterfaceMethodTable(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceOnConnectedEventCB(std::ofstream& stream,
-                                      const Interface& inf);
-  void GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
-                                         const Interface& inf);
-  void GenInterfaceOnReceivedEventCB(std::ofstream& stream,
-                                     const Interface& inf);
-  void GenInterfaceRegister(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceUnregister(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceGlobalVariables(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceContext(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceAddPrivileges(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceClientNumberGetter(std::ofstream& stream,
-                                      const Interface& inf);
+  void GenInterfaceBase(std::ofstream& stream, const Interface& inf);
 
- private:
-  void GenInterfaceContextDeclaration(std::ofstream& stream,
-                                      const Interface& inf);
-  void GenInterfaceContextConstructor(std::ofstream& stream,
-                                      const Interface& inf);
-  void GenInterfaceContextDestructor(std::ofstream& stream,
-                                     const Interface& inf);
-  void GenInterfaceContextFinder(std::ofstream& stream,
-                                 const Interface& inf);
-  void GenInterfaceContextTagSetter(std::ofstream& stream,
-                                    const Interface& inf);
-  void GenInterfaceContextTagGetter(std::ofstream& stream,
-                                    const Interface& inf);
-  void GenInterfaceContextSenderGetter(std::ofstream& stream,
-                                       const Interface& inf);
+  std::string GenMethodEnums(const Interface& inf);
+  std::string GenDelegateEnums(const Interface& inf);
 
- private:
-  void GenInterfaceDelegator(std::ofstream& stream, const std::string& id,
-                             const Declaration& decl);
-  void GenInterfaceDelegatorDeclaration(std::ofstream& stream,
-                                        const std::string& id,
-                                       const Declaration& decl);
-  void GenInterfaceDelegatorConstructor(std::ofstream& stream,
-                                      const std::string& id,
-                                       const Declaration& decl);
-  void GenInterfaceDelegatorDestructor(std::ofstream& stream,
-                                      const std::string& id,
-                                      const Declaration& decl);
-  void GenInterfaceDelegatorSerializer(std::ofstream& stream,
-                                      const std::string& id,
-                                      const Declaration& decl);
-  void GenInterfaceDelegatorDeserializer(std::ofstream& stream,
-                                        const std::string& id,
-                                        const Declaration& decl);
-  void GenInterfaceDelegatorCloner(std::ofstream& stream,
-                                  const std::string& id,
-                                  const Declaration& decl);
-  void GenInterfaceDelegatorInvoker(std::ofstream& stream,
-                                   const std::string& id,
-                                   const Declaration& decl);
-  void GenInterfaceDelegatorPortSetter(std::ofstream& stream,
-                                       const std::string& id,
-                                       const Declaration& decl);
+  std::string GenDelegateParams(const Interface& inf, const Declaration& decl);
+  std::string GenDelegateParamsCheck(const Interface& inf,
+      const Declaration& decl);
+  std::string GenDelegateParcelWrite(const Interface& inf,
+      const Declaration& decl);
 
- private:
-  std::string GetMethodString(const Interface& id, const Declaration& decl);
-  std::string GetAddEventCBString(const std::string& id);
-  std::string GetAddPrivilegeString(const std::string& id,
-                                    const Attribute& attr);
-  std::string GetTrustedModeString(const std::string& id,
-                                   const Attribute& attr);
+  std::string GenMethodHandlerArgsDecl(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodHandlerParcelRead(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodHandlerCallbackInvoke(const Declaration& decl);
+  std::string GenMethodHandlerParcelWrite(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodHandlerArgsFree(const Interface& inf,
+      const Declaration& decl);
+  std::string GenMethodHandlers(const Interface& inf);
+  std::string GenAccessControlSet(const Interface& inf);
 
  private:
   std::shared_ptr<Options> options_;
index a7ef172..d073959 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_STUB_BODY_GEN_CB_H_
 #define IDLC_C_GEN_C_STUB_BODY_GEN_CB_H_
 
-const char CB_INTERFACE_METHOD[] =
+constexpr const char CB_THREAD_ENABLE_DEF[] =
 R"__c_cb(
-static int __$$_method_$$(rpc_port_h port, rpc_port_parcel_h parcel, void *data)
-{
-    rpc_port_stub_$$_context_h context = data;
-    rpc_port_h callback_port;
-    int r;
+#define TIDL_THREAD_ENABLE 1
+)__c_cb";
 
-    r = rpc_port_stub_get_port(__$$_stub, RPC_PORT_PORT_CALLBACK, context->instance, &callback_port);
-    if (r != 0) {
-        _E("Failed to get callback port");
-        return -1;
-    }
+/**
+ * <PREFIX> The prefix of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_HANDLER_TYPE[] =
+R"__c_cb(
+typedef int (*<PREFIX>_method_handler)(rpc_port_h port, rpc_port_parcel_h parcel, void *data);
+)__c_cb";
 
-$$
-    return r;
-}
+/**
+ * <METHOD_ENUMS> The enumeration declarations of methods.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_ENUM_BASE[] =
+R"__c_cb(
+typedef enum {
+  <METHOD_ENUMS>
+} <PREFIX>_<NAME>_method_e;
 )__c_cb";
 
-const char CB_INTERFACE_METHOD_TABLE[] =
-R"__c_cb(static stub_method __$$_method_table[] = {$$
-};
+/**
+ * <UPPERCASE_PREFIX> The uppercase prefix of the interface.
+ * <UPPERCASE_NAME> The uppercase name of the interface.
+ * <UPPERCASE_METHOD_NAME> The uppercase method name of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_ENUM[] =
+R"__c_cb(
+<UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_<UPPERCASE_METHOD_NAME>,
 )__c_cb";
 
-const char CB_INTERFACE_METHOD_FORMAT[] =
+/**
+ * <DELEGATE_ENUMS> The enumeration declarations of deleagtes.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_ENUM_BASE[] =
 R"__c_cb(
-[$$] = $$,)__c_cb";
+typedef enum {
+  <DELEGATE_ENUMS>
+} <PREFIX>_<NAME>_delegate_e;
+)__c_cb";
 
-const char CB_INTERFACE_THREAD_METHODS[] =
+/**
+ * <UPPERCASE_PREFIX> The uppercase prefix of the interface.
+ * <UPPERCASE_NAME> The uppercase name of the interface.
+ * <UPPERCASE_DELEGATE_NAME> The uppercase delegate name of the interface.
+ * <NUMBER> The number of the delegate.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_ENUM[] =
 R"__c_cb(
-static int __run_pending_job(void)
-{
-    int cmd = -1;
-    job_h job;
-    int r = 0;
+<UPPERCASE_PREFIX>_<UPPERCASE_NAME>_DELEGATE_<UPPERCASE_DELEGATE_NAME> = <NUMBER>,
+)__c_cb";
 
-    if (g_queue_is_empty(__job_queue)) {
-        _E("Empty queue");
-        return -1;
-    }
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_BASE_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_s {
+  rpc_port_stub_h stub;
+  <PREFIX>_<NAME>_callback_s callback;
+  void *user_data;
+  GList* contexts;
+  GList* callback_ports;
+  GRecMutex mutex;
+} <PREFIX>_<NAME>_t;
+
+static <PREFIX>_<NAME>_t __<NAME>;
+)__c_cb";
 
-    job = g_queue_pop_head(__job_queue);
-    rpc_port_parcel_read_int32(job->parcel, &cmd);
-    if (cmd > 1 && cmd < (sizeof(__##_method_table) / sizeof(__##_method_table[0]))) {
-        if (__##_method_table[cmd])
-        r = __##_method_table[cmd](job->port, job->parcel, job->context);
-    } else {
-        _E("Unknown Command(%d)", cmd);
-        r = -1;
-    }
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_CONTEXT_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_context_s {
+  char *sender;
+  char *instance;
+  rpc_port_h port;
+  rpc_port_h callback_port;
+  void *tag;
+  <PREFIX>_<NAME>_callback_s callback;
+  void *user_data;
+#ifdef TIDL_THREAD_ENABLE
+  GThread *thread;
+  GQueue *queue;
+  GMutex mutex;
+  GCond cond;
+  bool done;
+#endif /* TIDL_THREAD_ENABLE */
+} <PREFIX>_<NAME>_context_t;
+
+static bool __<PREFIX>_<NAME>_exist_callback_port(rpc_port_h callback_port);
+)__c_cb";
 
-    __destroy_job(job);
-    return r;
-}
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate of the interface.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_<DELEGATE_NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  rpc_port_h port;
+  int id;
+  int seq_id;
+  bool once;
+  bool valid;
+} <PREFIX>_<NAME>_<DELEGATE_NAME>_t;
 )__c_cb";
 
-const char CB_INTERFACE_ON_CONNECTED[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_CONTEXT_BASE[] =
 R"__c_cb(
-static void __##_on_connected(const char *sender, const char *instance, void *data)
+static int __<PREFIX>_<NAME>_context_handle_request(<PREFIX>_<NAME>_context_h h, rpc_port_parcel_h parcel)
 {
-    rpc_port_stub_##_context_h context;
+  int ret = RPC_PORT_ERROR_NONE;
+  int cmd = -1;
+
+  rpc_port_parcel_read_int32(parcel, &cmd);
+  if (cmd > 1 && cmd < ARRAY_SIZE(__<NAME>_method_table)) {
+    if (__<NAME>_method_table[cmd])
+      ret = __<NAME>_method_table[cmd](h->port, parcel, h);
+  } else {
+    _W("Invalid protocol. cmd(%d)", cmd);
+    ret = RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  return ret;
+}
 
-    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
-    context = __create_##_context(sender, instance);
-    if (!context)
-        return;
+#ifdef TIDL_THREAD_ENABLE
+static int __<PREFIX>_<NAME>_context_push(<PREFIX>_<NAME>_context_h h, rpc_port_parcel_h parcel)
+{
+  g_mutex_lock(&h->mutex);
+  g_queue_push_tail(h->queue, parcel);
+  g_cond_signal(&h->cond);
+  g_mutex_unlock(&h->mutex);
 
-    if (context->callback.create)
-        context->callback.create(context, context->user_data);
-    __##_contexts = g_list_append(__##_contexts, context);
+  return 0;
 }
-)__c_cb";
 
-const char CB_INTERFACE_ON_DISCONNECTED[] =
-R"__c_cb(
-static void __##_on_disconnected(const char *sender, const char *instance, void *data)
+static rpc_port_parcel_h __<PREFIX>_<NAME>_context_wait_and_pop(<PREFIX>_<NAME>_context_h h)
 {
-    rpc_port_stub_##_context_h context;
+  rpc_port_parcel_h parcel;
 
-    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
-    context = __find_##_context(instance);
-    if (!context)
-        return;
+  g_mutex_lock(&h->mutex);
+  while (g_queue_is_empty(h->queue) && !h->done)
+    g_cond_wait(&h->cond, &h->mutex);
 
-    if (context->callback.terminate)
-        context->callback.terminate(context, context->user_data);
-    __##_contexts = g_list_remove(__##_contexts, context);
-    __destroy_##_context(context);
+  parcel = g_queue_pop_head(h->queue);
+  g_mutex_unlock(&h->mutex);
+
+  return parcel;
 }
-)__c_cb";
 
-const char CB_INTERFACE_ON_RECEIVED[] =
-R"__c_cb(
-static int __##_on_received(const char *sender, const char *instance, rpc_port_h port, void *data)
+static gpointer __<PREFIX>_<NAME>_context_thread_cb(gpointer user_data)
 {
-    rpc_port_stub_##_context_h context;
-    rpc_port_parcel_h parcel;
-    int cmd = -1;
-    int r;
-
-    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
-    context = __find_##_context(instance);
-    if (!context) {
-        _E("Failed to find ## context(%s)", instance);
-        return -1;
+  <PREFIX>_<NAME>_context_h h = user_data;
+  rpc_port_parcel_h parcel;
+
+  _W("START");
+  while (!h->done) {
+    parcel = __<PREFIX>_<NAME>_context_wait_and_pop(h);
+    if (parcel) {
+      __<PREFIX>_<NAME>_context_handle_request(h, parcel);
+      rpc_port_parcel_destroy(parcel);
     }
+  }
+  _W("END");
 
-    context->port = port;
-    r = rpc_port_parcel_create_from_port(&parcel, port);
-    if (r != 0) {
-        _E("Failed to create parcel from port");
-        return r;
-    }
+  return nullptr;
+}
+#endif /* TIDL_THREAD_ENABLE */
 
-    rpc_port_parcel_read_int32(parcel, &cmd);
-    if (cmd > 1 && cmd < (sizeof(__##_method_table) / sizeof(__##_method_table[0]))) {
-         if (__##_method_table[cmd])
-             r = __##_method_table[cmd](port, parcel, context);
-    } else {
-         _E("Unknown Command(%d)", cmd);
-         r = -1;
+static void __<PREFIX>_<NAME>_context_destroy(gpointer data)
+{
+  <PREFIX>_<NAME>_context_h h = data;
+#ifdef TIDL_THREAD_ENABLE
+  rpc_port_parcel_h parcel;
+#endif /* TIDL_THREAD_ENABLE */
+
+  if (h == nullptr)
+    return;
+
+#ifdef TIDL_THREAD_ENABLE
+  g_mutex_lock(&h->mutex);
+  h->done = true;
+  g_cond_signal(&h->cond);
+  g_mutex_unlock(&h->mutex);
+
+  if (h->thread) {
+    g_thread_join(h->thread);
+    g_thread_unref(h->thread);
+  }
+
+  g_mutex_clear(&h->mutex);
+  g_cond_clear(&h->cond);
+
+  if (h->queue) {
+    while (!g_queue_is_empty(h->queue)) {
+      parcel = g_queue_pop_head(h->queue);
+      rpc_port_parcel_destroy(parcel);
     }
 
-    rpc_port_parcel_destroy(parcel);
+    g_queue_free(h->queue);
+  }
+#endif /* TIDL_THREAD_ENABLE */
+
+  if (h->instance)
+    free(h->instance);
 
-    return r;
+  if (h->sender)
+    free(h->sender);
+
+  free(h);
 }
-)__c_cb";
 
-const char CB_INTERFACE_THREAD_ON_RECEIVED[] =
-R"__c_cb(
-static int __##_on_received(const char *sender, const char *instance, rpc_port_h port, void *data)
+static <PREFIX>_<NAME>_context_h __<PREFIX>_<NAME>_context_create(const char *sender, const char *instance, rpc_port_h callback_port)
 {
-    rpc_port_stub_##_context_h context;
-    int r;
+  <PREFIX>_<NAME>_context_t *handle;
+
+  if (sender == nullptr || instance == nullptr || callback_port == nullptr) {
+    _E("Invalid parameter");
+    return nullptr;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_context_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return nullptr;
+  }
+
+  handle->sender = strdup(sender);
+  if (handle->sender == nullptr) {
+    _E("Failed to duplicate sender");
+    __<PREFIX>_<NAME>_context_destroy(handle);
+    return nullptr;
+  }
+
+  handle->instance = strdup(instance);
+  if (handle->instance == nullptr) {
+    _E("Failed to duplicate instance");
+    __<PREFIX>_<NAME>_context_destroy(handle);
+    return nullptr;
+  }
+
+#ifdef TIDL_THREAD_ENABLE
+  g_mutex_init(&handle->mutex);
+  g_cond_init(&handle->cond);
+
+  handle->queue = g_queue_new();
+  if (handle->queue == nullptr) {
+    _E("Failed to create queue");
+    __<PREFIX>_<NAME>_context_destroy(handle);
+    return nullptr;
+  }
+
+  handle->thread = g_thread_new(instance, __<PREFIX>_<NAME>_context_thread_cb, handle);
+  if (handle->thread == nullptr) {
+    _E("Failed to create thread");
+    __<PREFIX>_<NAME>_context_destroy(handle);
+    return nullptr;
+  }
+#endif /* TIDL_THREAD_ENABLE */
+
+  handle->callback_port = callback_port;
+  handle->callback = __<NAME>.callback;
+  handle->user_data = __<NAME>.user_data;
+
+  return handle;
+}
 
-    _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance);
-    context = __find_##_context(instance);
-    if (!context) {
-        _E("Failed to find ## context(%s)", instance);
-        return -1;
-    }
-    r = __add_thread_queue(port, context);
+int <PREFIX>_<NAME>_context_set_tag(<PREFIX>_<NAME>_context_h context, void *tag)
+{
+  if (context == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    return r;
+  context->tag = tag;
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_THREAD_CREATE[] =
-R"__c_cb(
-__job_queue = g_queue_new();
-)__c_cb";
+int <PREFIX>_<NAME>_context_get_tag(<PREFIX>_<NAME>_context_h context, void **tag)
+{
+  if (context == nullptr || tag == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-const char CB_INTERFACE_THREAD_DESTROY[] =
-R"__c_cb(
-while (!g_queue_is_empty(__job_queue)) {
-    job = g_queue_pop_head(__job_queue);
-    __destroy_job(job);
+  *tag = context->tag;
+
+  return RPC_PORT_ERROR_NONE;
 }
-g_queue_free(__job_queue);
-__job_queue = NULL;
-)__c_cb";
 
-const char CB_INTERFACE_REGISTER[] =
-R"__c_cb(
-int rpc_port_stub_##_register(rpc_port_stub_##_callback_s *callback, void *user_data)
+int <PREFIX>_<NAME>_context_get_sender(<PREFIX>_<NAME>_context_h context, char **sender)
 {
-    int r;
+  char *value;
 
-    if (__##_stub) {
-        _W("Already exists");
-        return -1;
-    }
+  if (context == nullptr || sender == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    if (!callback) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  value = strdup(context->sender);
+  if (value == nullptr) {
+    _E("Failed to duplicate sender");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
 
-    __##_callback = *callback;
-    __##_user_data = user_data;
-    r = rpc_port_stub_create(&__##_stub, "##");
-    if (r != 0) {
-        _E("Failed to create stub handle");
-        return r;
-    }
-$$
-
-    r = rpc_port_stub_add_received_event_cb(__##_stub, __##_on_received, NULL);
-    if (r != 0) {
-        _E("Failed to add received event callback");
-        rpc_port_stub_destroy(__##_stub);
-        __##_stub = NULL;
-        return r;
-    }
+  *sender = value;
 
-    r = rpc_port_stub_add_connected_event_cb(__##_stub, __##_on_connected, NULL);
-    if (r != 0) {
-        _E("Failed to add connected event callback");
-        rpc_port_stub_destroy(__##_stub);
-        __##_stub = NULL;
-        return r;
-    }
+  return RPC_PORT_ERROR_NONE;
+}
 
-    r = rpc_port_stub_add_disconnected_event_cb(__##_stub, __##_on_disconnected, NULL);
-    if (r != 0) {
-        _E("Failed to add disconnected event callback");
-        rpc_port_stub_destroy(__##_stub);
-        __##_stub = NULL;
-        return r;
-    }
+int <PREFIX>_<NAME>_context_get_instance(<PREFIX>_<NAME>_context_h context, char **instance)
+{
+  char *value;
 
-    r = __##_add_privileges();
-    if (r != 0) {
-        _E("Failed to add privileges");
-        rpc_port_stub_destroy(__##_stub);
-        __##_stub = NULL;
-        return r;
-    }
+  if (context == nullptr || instance == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    r = rpc_port_stub_listen(__##_stub);
-    if (r != 0) {
-        _E("Failed to listen stub");
-        rpc_port_stub_destroy(__##_stub);
-        __##_stub = NULL;
-        return r;
-    }
+  value = strdup(context->instance);
+  if (value == nullptr) {
+    _E("Failed to duplicate instance");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
 
-    return 0;
+  *instance = value;
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_UNREGISTER[] =
-R"__c_cb(
-int rpc_port_stub_##_unregister(void)
+static <PREFIX>_<NAME>_context_h __<PREFIX>_<NAME>_find_context(const char *instance)
 {
-    int r;
-$$
-
-    if (!__##_stub)
-        return -1;
-
-    if (__##_contexts) {
-        g_list_free_full(__##_contexts, __destroy_##_context);
-        __##_contexts = NULL;
+  <PREFIX>_<NAME>_context_h context;
+  GList *iter;
+
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  iter = __<NAME>.contexts;
+  while (iter) {
+    context = iter->data;
+    if (!strcmp(context->instance, instance)) {
+      g_rec_mutex_unlock(&__<NAME>.mutex);
+      return context;
     }
 
-    r = rpc_port_stub_destroy(__##_stub);
-    __##_stub = NULL;
-$$
+    iter = g_list_next(iter);
+  }
+  g_rec_mutex_unlock(&__<NAME>.mutex);
 
-    return r;
+  return nullptr;
 }
-)__c_cb";
 
-const char CB_INTERFACE_CLIENT_NUMBER_GETTER[] =
-R"__c_cb(
-int rpc_port_stub_##_get_client_number(unsigned int *n)
+static void __<PREFIX>_<NAME>_add_context(<PREFIX>_<NAME>_context_h context)
 {
-    if (!n) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  __<NAME>.contexts = g_list_append(__<NAME>.contexts, context);
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+}
+
+static void __<PREFIX>_<NAME>_remove_context(<PREFIX>_<NAME>_context_h context)
+{
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  __<NAME>.contexts = g_list_remove(__<NAME>.contexts, context);
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+}
 
-    if (!__##_stub) {
-        _E("## Stub is not ready");
-        return -1;
+static bool __<PREFIX>_<NAME>_exist_callback_port(rpc_port_h callback_port)
+{
+  rpc_port_h port;
+  GList *iter;
+
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  iter = __<NAME>.callback_ports;
+  while (iter) {
+    port = iter->data;
+    if (port == callback_port) {
+      g_rec_mutex_unlock(&__<NAME>.mutex);
+      return true;
     }
 
-    *n = g_list_length(__##_contexts);
+    iter = g_list_next(iter);
+  }
+  g_rec_mutex_unlock(&__<NAME>.mutex);
 
-    return 0;
+  return false;
 }
-)__c_cb";
 
-const char CB_GLOBALS[] =
-R"__c_cb(
-static rpc_port_stub_h __##_stub;
-static rpc_port_stub_##_callback_s __##_callback;
-static void *__##_user_data;
-static GList *__##_contexts;
-)__c_cb";
+static void __<PREFIX>_<NAME>_add_callback_port(rpc_port_h callback_port)
+{
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  __<NAME>.callback_ports = g_list_append(__<NAME>.callback_ports, callback_port);
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+}
 
-const char CB_INTERFACE_DELEGATOR_DECL[] =
-R"__c_cb(
-struct $$_s {
-    rpc_port_parcelable_t parcelable;
-    rpc_port_h port;
-    int id;
-    int seq_id;
-    bool once;
-    bool valid;
-};
+static void __<PREFIX>_<NAME>_remove_callback_port(rpc_port_h callback_port)
+{
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  __<NAME>.callback_ports = g_list_remove(__<NAME>.callback_ports, callback_port);
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+}
 )__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_CTOR[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate of the interface.
+ * <DELEGATE_PARAMS> The parameters of the delegate.
+ * <DELEGATE_PARAMS_CHECK> The implementation to check whether arguments are nullptr or not
+ * <DELEGATE_ENUM_VALUE> The enumeration value of the method.
+ * <DELEGATE_PARCEL_WRITE> The implementation to write arguments to the parcel.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BASE[] =
 R"__c_cb(
-static int rpc_port_##_create(rpc_port_##_h *h)
+static void __<PREFIX>_<NAME>_<DELEGATE_NAME>_to(rpc_port_parcel_h parcel, void *user_data)
 {
-    struct ##_s *handle;
-    static int seq_num;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h h = user_data;
 
-    if (!h) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return;
+  }
 
-    handle = calloc(1, sizeof(struct ##_s));
-    if (!handle) {
-        _E("Out of memory");
-        return -1;
-    }
+  rpc_port_parcel_write_int32(parcel, h->id);
 
-    handle->parcelable.to = __##_to;
-    handle->parcelable.from = __##_from;
-    handle->id = $$_DELEGATE_$$;
-    handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1;
-    handle->once = false;
-    handle->valid = true;
+  rpc_port_parcel_write_int32(parcel, h->seq_id);
 
-    *h = handle;
+  rpc_port_parcel_write_bool(parcel, h->once);
 
-    return 0;
+  _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false");
 }
-)__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_DTOR[] =
-R"__c_cb(
-int rpc_port_##_destroy(rpc_port_##_h h)
+static void __<PREFIX>_<NAME>_<DELEGATE_NAME>_from(rpc_port_parcel_h parcel, void *user_data)
 {
-    if (!h) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h h = user_data;
 
-    free(h);
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
 
-    return 0;
-}
-)__c_cb";
+  rpc_port_parcel_read_int32(parcel, &h->id);
 
-const char CB_INTERFACE_DELEGATOR_SERIALIZER[] =
-R"__c_cb(
-static void __##_to(rpc_port_parcel_h parcel, void *data)
-{
-    rpc_port_##_h handle = data;
+  rpc_port_parcel_read_int32(parcel, &h->seq_id);
 
-    if (!handle) {
-        _E("Invalid parameter");
-        return;
-    }
+  rpc_port_parcel_read_bool(parcel, &h->once);
 
-    rpc_port_parcel_write_int32(parcel, handle->id);
-    rpc_port_parcel_write_int32(parcel, handle->seq_id);
-    rpc_port_parcel_write_bool(parcel, handle->once);
-    _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false");
+  _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false");
+  set_last_result(RPC_PORT_ERROR_NONE);
 }
-)__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_DESERIALIZER[] =
-R"__c_cb(
-static void __##_from(rpc_port_parcel_h parcel, void *data)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_create(<PREFIX>_<NAME>_<DELEGATE_NAME>_h *h)
 {
-    rpc_port_##_h handle = data;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_t *handle;
+  static int seq_num;
+
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_<DELEGATE_NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->parcelable.to = __<PREFIX>_<NAME>_<DELEGATE_NAME>_to;
+  handle->parcelable.from = __<PREFIX>_<NAME>_<DELEGATE_NAME>_from;
+  handle->id = <DELEGATE_ENUM_VALUE>;
+  handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1;
+  handle->once = false;
+  handle->valid = true;
+  _I("id(%d), seq_id(%d)", handle->id, handle->seq_id);
+
+  *h = handle;
+
+  return RPC_PORT_ERROR_NONE;
+}
 
-    if (!handle) {
-        _E("Invalid parameter");
-        return;
-    }
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h)
+{
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  _W("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false");
 
-    rpc_port_parcel_read_int32(parcel, &handle->id);
-    rpc_port_parcel_read_int32(parcel, &handle->seq_id);
-    rpc_port_parcel_read_bool(parcel, &handle->once);
-    _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false");
+  free(h);
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_CLONER[] =
-R"__c_cb(
-int rpc_port_##_clone(rpc_port_##_h h, rpc_port_##_h *clone)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_clone(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, <PREFIX>_<NAME>_<DELEGATE_NAME>_h *clone)
 {
-    rpc_port_##_h handle;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_h handle;
+  int ret;
 
-    if (!h || !clone) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    handle = calloc(1, sizeof(struct ##_s));
-    if (!handle) {
-        _E("Out of memory");
-        return -1;
-    }
+  ret = <PREFIX>_<NAME>_<DELEGATE_NAME>_create(&handle);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create handle. error(%d)", ret);
+    return ret;
+  }
 
-    handle->parcelable = h->parcelable;
-    handle->port = h->port;
-    handle->id = h->id;
-    handle->seq_id = h->seq_id;
-    handle->once = h->once;
-    handle->valid = h->valid;
-    _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false");
+  handle->port = h->port;
+  handle->seq_id = h->seq_id;
+  handle->once = h->once;
+  handle->valid = h->valid;
 
-    *clone = handle;
+  *clone = handle;
 
-    return 0;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_INVOKER[] =
-R"__c_cb(
-int rpc_port_$$_invoke($$)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *id)
 {
-    rpc_port_parcel_h parcel = NULL;
-    int r;
+  if (h == nullptr || id == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    if (!h || !h->port) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  *id = h->id;
 
-    if (h->once && !h->valid) {
-        _E("Invalid callback");
-        return -1;
-    }
+  return RPC_PORT_ERROR_NONE;
+}
 
-    rpc_port_parcel_create(&parcel);
-    if (!parcel) {
-        _E("Failed to create parcel");
-        return -1;
-    }
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_seq_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *seq_id)
+{
+  if (h == nullptr || seq_id == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    rpc_port_parcel_write_int32(parcel, $$_METHOD_Callback);
-    rpc_port_parcel_write(parcel, &h->parcelable, h);
-$$
-    r = rpc_port_parcel_send(parcel, h->port);
-    rpc_port_parcel_destroy(parcel);
-    h->valid = false;
+  *seq_id = h->seq_id;
 
-    return r;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_PORT_SETTER[] =
-R"__c_cb(
-int rpc_port_##_set_port(rpc_port_##_h h, rpc_port_h port)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_is_once(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, bool *once)
 {
-    if (!h || !port) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  if (h == nullptr || once == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    h->port = port;
+  *once = h->once;
 
-    return 0;
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_INTERFACE_CONTEXT_DECL[] =
-R"__c_cb(
-struct ##_context_s {
-    char *sender;
-    char *instance;
-    rpc_port_h port;
-    void *tag;
-    rpc_port_stub_##_callback_s callback;
-    void *user_data;
-$$
-};
-)__c_cb";
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_tag(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, char **tag)
+{
+  char *value;
+  char buf[128];
 
-const char CB_INTERFACE_CONTEXT_DECL_THREAD_ELEM[] =
-R"__c_cb(pthread_mutex_t mutex;
-pthread_cond_t cond;
-pthread_t thread;
-bool run_wait_queue;
-)__c_cb";
+  if (h == nullptr || tag == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-const char CB_INTERFACE_THREAD_FEATURE[] =
-R"__c_cb(
-typedef struct {
-    rpc_port_parcel_h parcel;
-    rpc_port_h port;
-    void *context;
-} job_s;
-typedef job_s *job_h;
+  snprintf(buf, sizeof(buf), "%d::%d", h->id, h->seq_id);
+  value = strdup(buf);
+  if (value == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
 
-static GQueue *__job_queue;
+  *tag = value;
 
-static int __run_pending_job(void);
+  return RPC_PORT_ERROR_NONE;
+}
 
-static void *__wait_queue(void *data)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_set_port(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, rpc_port_h port)
 {
-    rpc_port_stub_##_context_h context = (rpc_port_stub_##_context_h)data;
+  if (h == nullptr || port == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    while(context->run_wait_queue) {
-        pthread_mutex_lock(&context->mutex);
-        pthread_cond_wait(&context->cond, &context->mutex);
-        __run_pending_job();
-        pthread_mutex_unlock(&context->mutex);
-    }
+  h->port = port;
 
-    return NULL;
+  return RPC_PORT_ERROR_NONE;
 }
 
-static job_h __create_job(rpc_port_parcel_h parcel, rpc_port_h port, void *context)
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_invoke(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h<DELEGATE_PARAMS>)
 {
-    job_h job;
+  rpc_port_parcel_h parcel_;
+  int ret_;
 
-    job = (job_s *)calloc(1, sizeof(job_s));
-    if (!job) {
-        _E("Out of memory");
-        return NULL;
-    }
+  if (h == nullptr || h->port == nullptr<DELEGATE_PARAMS_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    job->parcel = parcel;
-    job->port = port;
-    job->context = context;
+  if (!__<PREFIX>_<NAME>_exist_callback_port(h->port)) {
+    _E("Not connected");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-    return job;
-}
+  if (h->once && !h->valid) {
+    _E("The delegate handle is already used");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
 
-static void __destroy_job(job_h job)
-{
-    rpc_port_parcel_destroy(job->parcel);
-    free(job);
+  ret_ = rpc_port_parcel_create(&parcel_);
+  if (ret_ != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle. error(%d)", ret_);
+    return ret_;
+  }
+
+  rpc_port_parcel_write_int32(parcel_, <DELEGATE_ENUM_VALUE>);
+
+  rpc_port_parcel_write(parcel_, &h->parcelable, h);
+
+  <DELEGATE_PARCEL_WRITE>
+  ret_ = rpc_port_parcel_send(parcel_, h->port);
+  rpc_port_parcel_destroy(parcel_);
+  h->valid = false;
+
+  return ret_;
 }
+)__c_cb";
 
-static int __add_thread_queue(rpc_port_h port, rpc_port_stub_##_context_h context)
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write(parcel_, &<ARG>->parcelable, <ARG>);
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_bundle(parcel_, <ARG>);
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_string(parcel_, <ARG>);
+)__c_cb";
+
+/**
+ * <PARCEL_TYPE> The type of the parcel.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BASE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel_, <ARG>);
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_NAME> The method name of the interface.
+ * <METHOD_HANDLER_ARGS_DECL> The declarations for arguments of the method.
+ * <METHOD_HANDLER_PARCEL_READ> The implementation to read the parameter from the parcel.
+ * <METHOD_HANDLER_CALLBACK_INVOKE> The implementation to invoke the callback function of the method.
+ * <METHOD_HANDLER_PARCEL_WRITE> The implementation to write the result to the parcel.
+ * <METHOD_HANDLER_ARGS_FREE> The implementation to release arguments.
+ */
+constexpr const char CB_INTERFACE_METHOD_HANDLER_BASE[] =
+R"__c_cb(
+static int __<PREFIX>_<NAME>_method_<METHOD_NAME>_handler(rpc_port_h port, rpc_port_parcel_h parcel, void *user_data)
 {
-    rpc_port_parcel_h parcel;
-    job_h job;
-    int r;
+  <PREFIX>_<NAME>_context_h context_ = user_data;
+  rpc_port_h callback_port_;
+  int ret_;
+  <METHOD_HANDLER_ARGS_DECL>
 
-    r = rpc_port_parcel_create_from_port(&parcel, port);
-    if (r != 0) {
-        _E("Failed to create parcel from port");
-        return r;
-    }
+  ret_ = rpc_port_stub_get_port(__<NAME>.stub, RPC_PORT_PORT_CALLBACK, context_->instance, &callback_port_);
+  if (ret_ != RPC_PORT_ERROR_NONE) {
+    _E("Failed to get callback port. error(%d)", ret_);
+    goto out;
+  }
 
-    job = __create_job(parcel, port, context);
-    g_queue_push_tail(__job_queue, job);
-    if (g_queue_is_empty(__job_queue)) {
-        _E("Empty queue ##");
-        return -1;
-    }
+  <METHOD_HANDLER_PARCEL_READ>
+  <METHOD_HANDLER_CALLBACK_INVOKE>
+  <METHOD_HANDLER_PARCEL_WRITE>
 
-    pthread_mutex_lock(&context->mutex);
-    pthread_cond_signal(&context->cond);
-    pthread_mutex_unlock(&context->mutex);
+out:
+  <METHOD_HANDLER_ARGS_FREE>
 
-    return 0;
+  return ret_;
 }
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_CTOR[] =
+/**
+ * <ARG> The argument.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface
+ */
+constexpr const char CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ[] =
 R"__c_cb(
-static struct ##_context_s *__create_##_context(const char *sender, const char *instance)
-{
-    struct ##_context_s *handle;
+ret_ = <PREFIX>_<NAME>_create(&<ARG>);
+if (ret_ != RPC_PORT_ERROR_NONE) {
+  _E("Failed to create handle. error(%d)", ret_);
+  goto out;
+}
 
-    handle = calloc(1, sizeof(struct ##_context_s));
-    if (!handle) {
-        _E("Out of memory");
-        return NULL;
-    }
+<PREFIX>_<NAME>_set_port(<ARG>, callback_port_);
+rpc_port_parcel_read(parcel, &<ARG>->parcelable, <ARG>);
+ret_ = get_last_result();
+if (ret_ != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data. error(%d)", ret_);
+  goto out;
+}
+)__c_cb";
 
-    handle->sender = strdup(sender);
-    if (!handle->sender) {
-        _E("Out of memory");
-        free(handle);
-        return NULL;
-    }
+/**
+ * <ARG> The name of the value.
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ */
+constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ[] =
+R"__c_cb(
+ret_ = <PREFIX>_<NAME>_create(&<ARG>);
+if (ret_ != RPC_PORT_ERROR_NONE) {
+  _E("Failed to create handle. error(%d)", ret_);
+  goto out;
+}
 
-    handle->instance = strdup(instance);
-    if (!handle->instance) {
-        _E("Out of memory");
-        free(handle->sender);
-        free(handle);
-        return NULL;
-    }
+rpc_port_parcel_read(parcel, &<ARG>->parcelable, <ARG>);
+ret_ = get_last_result();
+if (ret_ != RPC_PORT_ERROR_NONE) {
+  _E("Failed to read data. error(%d)", ret_);
+  goto out;
+}
+)__c_cb";
 
-    handle->callback = __##_callback;
-    handle->user_data = __##_user_data;
-$$
-    return handle;
+/**
+ * <ARG> The name of the value.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ[] =
+R"__c_cb(
+rpc_port_parcel_read_bundle(parcel, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY;
+  goto out;
 }
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_CTOR_THREAD_IMPL[] =
+/**
+ * <ARG> The name of the value.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] =
 R"__c_cb(
-pthread_mutex_init(&handle->mutex, NULL);
-pthread_cond_init(&handle->cond, NULL);
-handle->run_wait_queue = true;
-if (pthread_create(&handle->thread, NULL, &__wait_queue, (void *)handle) < 0) {
-    _E("Fail to create thread");
-    free(handle->instance);
-    free(handle->sender);
-    free(handle);
-    return NULL;
+rpc_port_parcel_read_string(parcel, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY;
+  goto out;
 }
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_DTOR[] =
+/**
+ * <PARCEL_TYPE> The type of the parcel.
+ * <ARG> The name of the value.
+ */
+constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_READ[] =
 R"__c_cb(
-static void __destroy_##_context(gpointer data)
-{
-    struct ##_context_s *handle = data;
-$$
-    if (!handle) {
-        _E("Critical error!");
-        return;
-    }
+rpc_port_parcel_read_<PARCEL_TYPE>(parcel, &<ARG>);
+)__c_cb";
 
-    free(handle->instance);
-    free(handle->sender);
-$$
-    free(handle);
+/**
+ * <RES_SET> The implemention to set the result of the callback function.
+ * <METHOD_NAME> The name of the method of the interface.
+ * <METHOD_ARGS> The arguments of the method.
+ */
+constexpr const char CB_INTERFACE_METHOD_CALLBACK_INVOKE[] =
+R"__c_cb(
+if (context_->callback.<METHOD_NAME>)
+  <RES_SET>context_->callback.<METHOD_NAME>(context_<METHOD_ARGS>, context_->user_data);
+)__c_cb";
+
+/**
+ * <UPPERCASE_NAME> The uppercase name of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_PARCEL_WRITE_PRE[] =
+R"__c_cb(
+ret_ = rpc_port_parcel_create(&parcel_);
+if (ret_ != RPC_PORT_ERROR_NONE) {
+  _E("Failed to create parcel handle. error(%d)", ret_);
+  goto out;
 }
+
+rpc_port_parcel_write_int32(parcel_, RPC_PORT_STUB_<UPPERCASE_NAME>_METHOD_RESULT_);
+)__c_cb";
+
+constexpr const char CB_INTERFACE_METHOD_PARCEL_WRITE_POST[] =
+R"__c_cb(
+ret_ = rpc_port_parcel_send(parcel_, port);
+rpc_port_parcel_destroy(parcel_);
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_DTOR_THREAD_VARS[] =
-R"__c_cb(void *retval = NULL;
-int ret;
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write(parcel_, &<ARG>->parcelable, <ARG>);
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_DTOR_THREAD_IMPL[] =
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE[] =
 R"__c_cb(
-handle->run_wait_queue = false;
-pthread_mutex_lock(&handle->mutex);
-pthread_cond_signal(&handle->cond);
-pthread_mutex_unlock(&handle->mutex);
+rpc_port_parcel_write_bundle(parcel_, <ARG>);
+)__c_cb";
 
-ret = pthread_join(handle->thread, &retval);
-if (ret != 0)
-    _E("joining thread error [%d].", ret);
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_string(parcel_, <ARG>);
+)__c_cb";
 
-pthread_cond_destroy(&handle->cond);
-pthread_mutex_destroy(&handle->mutex);
+/**
+ * <PARCEL_TYPE> The type of the parcel.
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel_, <ARG>);
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_FINDER[] =
+/**
+ * <ARG> The argument.
+ * <PREFIX> The prefix of the structure.
+ * <NAME> The name of the structure.
+ */
+constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_FREE[] =
 R"__c_cb(
-static struct ##_context_s *__find_##_context(const char *instance)
-{
-    struct ##_context_s *handle;
-    GList *iter;
+if (<ARG>)
+  <PREFIX>_<NAME>_destroy(<ARG>);
+)__c_cb";
 
-    iter = __##_contexts;
-    while (iter) {
-        handle = (struct ##_context_s *)iter->data;
-        if (!strcmp(handle->instance, instance))
-            return handle;
-        iter = g_list_next(iter);
-    }
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_FREE[] =
+R"__c_cb(
+if (<ARG>)
+  bundle_free(<ARG>);
+)__c_cb";
 
-    return NULL;
-}
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_FREE[] =
+R"__c_cb(
+if (<ARG>)
+  free(<ARG>);
 )__c_cb";
 
-const char CB_INTERFACE_CONTEXT_TAG_SETTER[] =
+/**
+ * <NAME> The name of the interface.
+ * <METHOD_HANDLERS> The declarations of method handlers.
+ */
+constexpr const char CB_INTERFACE_METHOD_TABLE[] =
 R"__c_cb(
-int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void *tag)
+static rpc_port_stub_method_handler __<NAME>_method_table[] = {
+  <METHOD_HANDLERS>
+};
+)__c_cb";
+
+/**
+ * <ENUM_VALUE> The enumeration value of the method.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_NAME> The method name of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_HANDLER[] =
+R"__c_cb(
+[<ENUM_VALUE>] = __<PREFIX>_<NAME>_method_<METHOD_NAME>_handler,
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <ACCESS_CONTROL_SET> The implmentation to set the access control the stub handle.
+ */
+constexpr const char CB_INTERFACE_BASE[] =
+R"__c_cb(
+static void __<PREFIX>_<NAME>_connected_event_cb(const char *sender, const char *instance, void *user_data)
 {
-    if (!ctx) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  <PREFIX>_<NAME>_context_h context;
+  rpc_port_h callback_port = nullptr;
+  int ret;
+
+  _W("sender(%s), instance(%s)", sender, instance);
+  ret = rpc_port_stub_get_port(__<NAME>.stub, RPC_PORT_PORT_CALLBACK, instance, &callback_port);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to get callback port. error(%d)", ret);
+    return;
+  }
+
+  context = __<PREFIX>_<NAME>_context_create(sender, instance, callback_port);
+  if (context == nullptr)
+    return;
+
+  __<PREFIX>_<NAME>_add_context(context);
+  __<PREFIX>_<NAME>_add_callback_port(context->callback_port);
+  context->callback.create(context, context->user_data);
+}
+
+static void __<PREFIX>_<NAME>_disconnected_event_cb(const char *sender, const char *instance, void *user_data)
+{
+  <PREFIX>_<NAME>_context_h context;
+
 
-    ctx->tag = tag;
+  _W("sender(%s), instance(%s)", sender, instance);
+  context = __<PREFIX>_<NAME>_find_context(instance);
+  if (context == nullptr)
+    return;
 
-    return 0;
+  __<PREFIX>_<NAME>_remove_callback_port(context->callback_port);
+  context->callback.terminate(context, context->user_data);
+  __<PREFIX>_<NAME>_remove_context(context);
+  __<PREFIX>_<NAME>_context_destroy(context);
 }
-)__c_cb";
 
-const char CB_INTERFACE_CONTEXT_TAG_GETTER[] =
-R"__c_cb(
-int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void **tag)
+static int __<PREFIX>_<NAME>_received_event_cb(const char *sender, const char *instance, rpc_port_h port, void *user_data)
 {
-    if (!ctx || !tag) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  <PREFIX>_<NAME>_context_h context;
+  rpc_port_parcel_h parcel;
+  int ret;
+
+  _W("sender(%s), instance(%s)", sender, instance);
+  context = __<PREFIX>_<NAME>_find_context(instance);
+  if (context == nullptr) {
+    _E("Failed to find context. instance(%s)", instance);
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  context->port = port;
+  ret = rpc_port_parcel_create_from_port(&parcel, port);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle from port. error(%d)", ret);
+    return ret;
+  }
+
+#ifdef TIDL_THREAD_ENABLE
+  ret = __<PREFIX>_<NAME>_context_push(context, parcel);
+#else
+  ret = __<PREFIX>_<NAME>_context_handle_request(context, parcel);
+  rpc_port_parcel_destroy(parcel);
+#endif /* TIDL_THREAD_ENABLE */
+
+  return ret;
+}
 
-    *tag = ctx->tag;
+static int __<PREFIX>_<NAME>_set_access_control(void)
+{
+  int ret = RPC_PORT_ERROR_NONE;
+
+  <ACCESS_CONTROL_SET>
 
-    return 0;
+  return ret;
 }
-)__c_cb";
 
-const char CB_INTERFACE_CONTEXT_GET_SENDER[] =
-R"__c_cb(
-int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char **sender)
+int <PREFIX>_<NAME>_register(rpc_port_stub_<NAME>_callback_s *callback, void *user_data)
 {
-    if (!ctx || !sender) {
-        _E("Invalid parameter");
-        return -1;
-    }
+  int ret;
+
+  if (callback == nullptr || callback->create == nullptr || callback->terminate == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  if (__<NAME>.stub) {
+    _E("Already exists");
+    return RPC_PORT_ERROR_NONE;
+  }
+
+  g_rec_mutex_init(&__<NAME>.mutex);
+  __<NAME>.callback = *callback;
+  __<NAME>.user_data = user_data;
+
+  ret = rpc_port_stub_create(&__<NAME>.stub, "<NAME>");
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create stub handle. error(%d)", ret);
+    <PREFIX>_<NAME>_unregister();
+    return ret;
+  }
+
+  ret = rpc_port_stub_add_received_event_cb(__<NAME>.stub, __<PREFIX>_<NAME>_received_event_cb, &__<NAME>);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add received event callback");
+    <PREFIX>_<NAME>_unregister();
+    return ret;
+  }
+
+  ret = rpc_port_stub_add_connected_event_cb(__<NAME>.stub, __<PREFIX>_<NAME>_connected_event_cb, &__<NAME>);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add connected event callback");
+    <PREFIX>_<NAME>_unregister();
+    return ret;
+  }
+
+  ret = rpc_port_stub_add_disconnected_event_cb(__<NAME>.stub, __<PREFIX>_<NAME>_disconnected_event_cb, &__<NAME>);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add disconnected event callback");
+    <PREFIX>_<NAME>_unregister();
+    return ret;
+  }
+
+  ret = __<PREFIX>_<NAME>_set_access_control();
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to add privileges");
+    <PREFIX>_<NAME>_unregister();
+    return ret;
+  }
+
+  ret = rpc_port_stub_listen(__<NAME>.stub);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to listen events. error(%d)", ret);
+    <PREFIX>_<NAME>_unregister();
+    return ret;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
 
-    *sender = strdup(ctx->sender);
-    if (*sender == NULL) {
-        _E("Out of memory");
-        return -1;
-    }
+int <PREFIX>_<NAME>_unregister(void)
+{
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+  g_rec_mutex_clear(&__<NAME>.mutex);
 
-    return 0;
+  if (__<NAME>.contexts) {
+    g_list_free_full(__<NAME>.contexts, __<PREFIX>_<NAME>_context_destroy);
+    __<NAME>.contexts = nullptr;
+  }
+
+  if (__<NAME>.stub) {
+    rpc_port_stub_destroy(__<NAME>.stub);
+    __<NAME>.stub = nullptr;
+  }
+
+  return RPC_PORT_ERROR_NONE;
 }
-)__c_cb";
 
-const char CB_STUB_METHOD_TYPE[] =
-R"__c_cb(
-typedef int (*stub_method)(rpc_port_h, rpc_port_parcel_h, void *data);
-)__c_cb";
+int <PREFIX>_<NAME>_foreach_context(<PREFIX>_<NAME>_context_cb callback, void *user_data)
+{
+  <PREFIX>_<NAME>_context_h context;
+  GList *iter;
+
+  if (callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  iter = __<NAME>.contexts;
+  while (iter) {
+    context = iter->data;
+    if (!callback(context, user_data))
+      break;
+
+    iter = g_list_next(iter);
+  }
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+
+  return RPC_PORT_ERROR_NONE;
+}
 
-const char CB_INTERFACE_ADD_PRIVILEGE[] =
-R"__c_cb(
-static int __$$_add_privileges(void)
+int <PREFIX>_<NAME>_get_client_number(unsigned int *client_number)
 {
-$$
-    return 0;
+  if (client_number == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  if (__<NAME>.stub == nullptr) {
+    _E("Invalid context");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  g_rec_mutex_lock(&__<NAME>.mutex);
+  *client_number = g_list_length(__<NAME>.contexts);
+  g_rec_mutex_unlock(&__<NAME>.mutex);
+
+  return RPC_PORT_ERROR_NONE;
 }
 )__c_cb";
 
-const char CB_INTERFACE_PRIVILEGE_BLOCK[] =
-R"__c_cb(r = $$;
-if (r != 0) {
-    _E("Failed to add privilege($$)");
-    return r;
+/**
+ * <NAME> The name of the interface.
+ * <PRIVILEGE> The privilege name.
+ */
+constexpr const char CB_INTERFACE_PRIVILEGE_ADD[] =
+R"__c_cb(
+ret = rpc_port_stub_add_privilege(__<NAME>.stub, "<PRIVILEGE>");
+if (ret != RPC_PORT_ERROR_NONE) {
+  _E("Failed to add privilege. error(%d)", ret);
+  return ret;
 }
 )__c_cb";
 
-const char CB_INTERFACE_TRUSTED_MODE_BLOCK[] =
-R"__c_cb(r = $$;
-if (r != 0) {
-    _E("Failed to set trusted mode($$)");
-    return r;
+/**
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_TRUSTED_SET[] =
+R"__c_cb(
+ret = rpc_port_stub_set_trusted(__<NAME>.stub, true);
+if (ret != RPC_PORT_ERROR_NONE) {
+  _E("Failed to set trusted mode. error(%d)", ret);
+  return ret;
 }
 )__c_cb";
 
index 426cd6d..8d9b4a0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
@@ -30,7 +30,10 @@ void CStubHeaderGen::OnInitGen(std::ofstream& stream) {
   GenPragmaOnce(stream);
   GenIncludeDefaultHeaders(stream, false);
   GenExplicitLinkageOpen(stream);
+  GenStructureHandles(stream);
+  GenInterfaceHandles(stream);
   GenStructures(stream);
+  GenInterfaceCallbacks(stream);
   GenInterfaces(stream);
 }
 
@@ -38,6 +41,96 @@ void CStubHeaderGen::OnFiniGen(std::ofstream& stream) {
   GenExplicitLinkageClose(stream);
 }
 
+void CStubHeaderGen::GenInterfaceHandles(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& inf = static_cast<const Interface&>(*b);
+    GenInterfaceContextHandle(stream, inf);
+    for (auto& d : inf.GetDeclarations().GetDecls()) {
+      if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
+        continue;
+
+      GenInterfaceDelegateHandle(stream, inf, *d);
+    }
+  }
+}
+
+// @see #CB_INTERFACE_CONTEXT_HANDLE
+void CStubHeaderGen::GenInterfaceContextHandle(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_HANDLE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_DELEGATE_HANDLE
+void CStubHeaderGen::GenInterfaceDelegateHandle(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_HANDLE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+
+  stream << SmartIndent(code);
+}
+
+void CStubHeaderGen::GenInterfaceCallbacks(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& inf = static_cast<const Interface&>(*b);
+    GenInterfaceCallbackBase(stream, inf);
+    for (auto& d : inf.GetDeclarations().GetDecls()) {
+      if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+        continue;
+
+      GenInterfaceMethodCallbackBase(stream, inf, *d);
+    }
+  }
+}
+
+// @see #CB_INTERFACE_CALLBACK_BASE
+void CStubHeaderGen::GenInterfaceCallbackBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_CALLBACK_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+
+  stream << SmartIndent(code);
+}
+
+std::string CStubHeaderGen::GenMethodParams(const Interface& inf,
+    const Declaration& decl) {
+  std::string params;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, inf) +
+        p->GetID();
+  }
+
+  return params;
+}
+
+// @see #CB_INTERFACE_METHOD_CALLBACK_BASE
+void CStubHeaderGen::GenInterfaceMethodCallbackBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_BASE,
+      "<RETURN_TYPE>", GetReturnTypeString(decl.GetType()));
+  code = ReplaceAll(code, "<PREFIX>", GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<METHOD_NAME>", decl.GetID());
+  code = ReplaceAll(code, "<METHOD_PARAMS>", GenMethodParams(inf, decl));
+
+  stream << SmartIndent(code);
+}
+
 void CStubHeaderGen::GenInterfaces(std::ofstream& stream) {
   for (auto& i : GetDocument().GetBlocks()) {
     if (i->GetType() != Block::TYPE_INTERFACE)
@@ -49,156 +142,85 @@ void CStubHeaderGen::GenInterfaces(std::ofstream& stream) {
 }
 
 void CStubHeaderGen::GenInterface(std::ofstream& stream,
-                                  const Interface& inf) {
-  GenInterfaceContext(stream, inf);
-  GenInterfaceDelegators(stream, inf);
-  GenInterfaceDeclaration(stream, inf);
-  GenInterfaceRegister(stream, inf);
-  GenInterfaceUnregister(stream, inf);
-  GenInterfaceClientNumberGetter(stream, inf);
-}
-
-void CStubHeaderGen::GenInterfaceDeclaration(std::ofstream& stream,
-                                             const Interface& inf) {
-  stream << SmartIndent(GenTemplateString(ReplaceAll(
-        CB_INTERFACE_DECL, "##", GetInterfaceIdWithNamespace(inf)),
-        [&]()->std::string {
-          std::string str;
-          for (auto& i : inf.GetDeclarations().GetDecls()) {
-            if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
-              continue;
-            str += NLine(1);
-            str += GenTemplateString(CB_INTERFACE_CALLBACK,
-                [&]()->std::string {
-                  return GetReturnTypeString(i->GetType());
-                },
-                [&]()->std::string {
-                  return i->GetID();
-                },
-                [&]()->std::string {
-                  return GetInterfaceIdWithNamespace(inf);
-                },
-                [&]()->std::string {
-                  std::string s;
-                  for (auto& p : i->GetParameters().GetParams()) {
-                    if (IsDelegateType(inf, p->GetParameterType()
-                        .GetBaseType())) {
-                      s += "rpc_port_" + GetInterfaceIdWithNamespace(inf)
-                        + "_" + p->GetParameterType().GetBaseType().ToString()
-                        + "_h " + p->GetID();
-                    } else {
-                      s += GetParamTypeString(p->GetParameterType()
-                          .GetDirection(), p->GetParameterType().GetBaseType())
-                        + p->GetID();
-                    }
-                    s += ", ";
-                  }
-                  return s;
-                });
-          }
-          return str;
-        }));
-}
-
-void CStubHeaderGen::GenInterfaceContext(std::ofstream& stream,
-                                         const Interface& inf) {
-  GenInterfaceContextDeclaration(stream, inf);
-  GenInterfaceContextTagSetter(stream, inf);
-  GenInterfaceContextTagGetter(stream, inf);
-  GenInterfaceContextSenderGetter(stream, inf);
-}
-
-void CStubHeaderGen::GenInterfaceContextDeclaration(
-    std::ofstream& stream, const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CONTEXT_DECL, "##",
-      GetInterfaceIdWithNamespace(inf));
-}
-
-void CStubHeaderGen::GenInterfaceContextTagSetter(
-    std::ofstream& stream, const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CONTEXT_SET_TAG, "##",
-      GetInterfaceIdWithNamespace(inf));
-}
-
-void CStubHeaderGen::GenInterfaceContextTagGetter(
-    std::ofstream& stream, const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CONTEXT_GET_TAG, "##",
-      GetInterfaceIdWithNamespace(inf));
-}
-
-void CStubHeaderGen::GenInterfaceContextSenderGetter(
-    std::ofstream& stream, const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CONTEXT_GET_SENDER, "##",
-      GetInterfaceIdWithNamespace(inf));
-}
-
-void CStubHeaderGen::GenInterfaceDelegators(std::ofstream& stream,
-                                            const Interface& inf) {
-  for (auto& i : inf.GetDeclarations().GetDecls()) {
-    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+    const Interface& inf) {
+  GenInterfaceContextBase(stream, inf);
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
       continue;
-    GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i);
+
+    GenInterfaceDelegateBase(stream, inf, *d);
   }
-}
 
-void CStubHeaderGen::GenInterfaceDelegator(std::ofstream& stream,
-                                           const std::string& id,
-                                           const Declaration& decl) {
-  GenInterfaceDelegatorDeclaration(stream, id, decl);
-  GenInterfaceDelegatorDestructor(stream, id, decl);
-  GenInterfaceDelegatorCloner(stream, id, decl);
-  GenInterfaceDelegatorInvoker(stream, id, decl);
+  GenInterfaceBase(stream, inf);
 }
 
-void CStubHeaderGen::GenInterfaceDelegatorDeclaration(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << ReplaceAll(
-      CB_INTERFACE_DELEGATOR_DECL, "##", id + "_" + decl.GetID());
-}
+// @see #CB_INTERFACE_CONTEXT_BASE
+void CStubHeaderGen::GenInterfaceContextBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
 
-void CStubHeaderGen::GenInterfaceDelegatorDestructor(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << ReplaceAll(
-      CB_INTERFACE_DELEGATOR_DTOR, "##", id + "_" + decl.GetID());
+  stream << SmartIndent(code);
 }
 
-void CStubHeaderGen::GenInterfaceDelegatorCloner(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << ReplaceAll(
-      CB_INTERFACE_DELEGATOR_CLONER, "##", id + "_" + decl.GetID());
-}
+std::string CStubHeaderGen::GenDelegateParams(const Interface& inf,
+    const Declaration& decl) {
+  std::string params;
+  for (auto& p : decl.GetParameters().GetParams()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, inf) +
+        p->GetID();
+  }
 
-void CStubHeaderGen::GenInterfaceDelegatorInvoker(
-    std::ofstream& stream, const std::string& id, const Declaration& decl) {
-  stream << GenTemplateString(ReplaceAll(
-      CB_INTERFACE_DELEGATOR_INVOKER, "##", id + "_" + decl.GetID()),
-      [&]()->std::string {
-        std::string str;
-        for (auto& i : decl.GetParameters().GetParams()) {
-          str += ", ";
-          str += GetParamTypeString(i->GetParameterType().GetDirection(),
-              i->GetParameterType().GetBaseType()) + i->GetID();
-        }
-        return str;
-      });
+  return params;
 }
 
-void CStubHeaderGen::GenInterfaceRegister(std::ofstream& stream,
-                                          const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_REGISTER, "##",
-      GetInterfaceIdWithNamespace(inf));
+// @see #CB_INTERFACE_DELEGATE_BASE
+void CStubHeaderGen::GenInterfaceDelegateBase(std::ofstream& stream,
+    const Interface& inf, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<DELEGATE_NAME>", decl.GetID());
+  code = ReplaceAll(code, "<DELEGATE_PARAMS>", GenDelegateParams(inf, decl));
+
+  stream << SmartIndent(code);
 }
 
-void CStubHeaderGen::GenInterfaceUnregister(std::ofstream& stream,
-                                            const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_UNREGISTER, "##",
-      GetInterfaceIdWithNamespace(inf));
+// @see #CB_INTERFACE_METHOD_CALLBACK_DECL
+std::string CStubHeaderGen::GenMethodCallbackDecls(const Interface& inf) {
+  std::string method_callback_decls;
+  for (auto& d : inf.GetDeclarations().GetDecls()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    std::string method_callback_decl = ReplaceAll(
+        CB_INTERFACE_METHOD_CALLBACK_DECL, "<PREFIX>", GetHandlePrefix());
+    method_callback_decl = ReplaceAll(method_callback_decl, "<NAME>",
+        inf.GetID());
+    method_callback_decl = ReplaceAll(method_callback_decl, "<METHOD_NAME>",
+        d->GetID());
+
+    method_callback_decl = RemoveLine(method_callback_decl);
+    method_callback_decls += RemoveLine(method_callback_decl, 2);
+  }
+
+  return method_callback_decls;
 }
 
-void CStubHeaderGen::GenInterfaceClientNumberGetter(std::ofstream& stream,
-                                                    const Interface& inf) {
-  stream << ReplaceAll(CB_INTERFACE_CLIENT_NUMBER_GETTER, "##",
-      GetInterfaceIdWithNamespace(inf));
+// @see #CB_INTERFACE_BASE
+void CStubHeaderGen::GenInterfaceBase(std::ofstream& stream,
+    const Interface& inf) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", inf.GetID());
+  code = ReplaceAll(code, "<METHOD_CALLBACK_DECLS>",
+      GenMethodCallbackDecls(inf));
+
+  stream << SmartIndent(code);
 }
 
 }  // namespace tidl
index 43d2e53..f7c9f4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
@@ -33,42 +33,27 @@ class CStubHeaderGen : public CHeaderGeneratorBase {
   void OnFiniGen(std::ofstream& stream) override;
 
  private:
+  void GenInterfaceHandles(std::ofstream& stream);
+  void GenInterfaceContextHandle(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+
+  void GenInterfaceCallbacks(std::ofstream& stream);
+  void GenInterfaceCallbackBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethodCallbackBase(std::ofstream& stream,
+      const Interface& inf, const Declaration& decl);
+
   void GenInterfaces(std::ofstream& stream);
   void GenInterface(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceContext(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceRegister(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceUnregister(std::ofstream& stream, const Interface& inf);
-  void GenInterfaceClientNumberGetter(std::ofstream& stream,
-                                       const Interface& inf);
 
- private:
-  void GenInterfaceContextDeclaration(std::ofstream& stream,
-                                      const Interface& inf);
-  void GenInterfaceContextTagSetter(std::ofstream& stream,
-                                    const Interface& inf);
-  void GenInterfaceContextTagGetter(std::ofstream& stream,
-                                    const Interface& inf);
-  void GenInterfaceContextSenderGetter(std::ofstream& stream,
-                                       const Interface& inf);
+  void GenInterfaceContextBase(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf,
+      const Declaration& decl);
+  void GenInterfaceBase(std::ofstream& stream, const Interface& inf);
 
- private:
-  void GenInterfaceDelegator(std::ofstream& stream,
-                             const std::string& id,
-                             const Declaration& decl);
-  void GenInterfaceDelegatorDeclaration(std::ofstream& stream,
-                                        const std::string& id,
-                                        const Declaration& decl);
-  void GenInterfaceDelegatorDestructor(std::ofstream& stream,
-                                      const std::string& id,
-                                      const Declaration& decl);
-  void GenInterfaceDelegatorCloner(std::ofstream& stream,
-                                  const std::string& id,
-                                  const Declaration& decl);
-  void GenInterfaceDelegatorInvoker(std::ofstream& stream,
-                                   const std::string& id,
-                                   const Declaration& decl);
+  std::string GenDelegateParams(const Interface& inf, const Declaration& decl);
+  std::string GenMethodParams(const Interface& inf, const Declaration& decl);
+  std::string GenMethodCallbackDecls(const Interface& inf);
 };
 
 }  // namespace tidl
index 49e37f0..d4e27f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 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.
 #ifndef IDLC_C_GEN_C_STUB_HEADER_GEN_CB_H_
 #define IDLC_C_GEN_C_STUB_HEADER_GEN_CB_H_
 
-const char CB_INTERFACE_DECL[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_CONTEXT_HANDLE[] =
 R"__c_cb(
-typedef struct {
-    void (*create)(rpc_port_stub_##_context_h context, void *user_data);
-    void (*terminate)(rpc_port_stub_##_context_h context, void *user_data);
-$$
-} rpc_port_stub_##_callback_s;
+/**
+ * @brief The <PREFIX>_<NAME>_context handle.
+ */
+typedef struct <PREFIX>_<NAME>_context_s *<PREFIX>_<NAME>_context_h;
 )__c_cb";
 
-const char CB_INTERFACE_CALLBACK[] =
-R"__c_cb($$(*$$)(rpc_port_stub_$$_context_h context, $$void *user_data);)__c_cb";
-
-const char CB_INTERFACE_CONTEXT_DECL[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_CONTEXT_BASE[] =
 R"__c_cb(
-typedef struct ##_context_s* rpc_port_stub_##_context_h;
-)__c_cb";
+/**
+ * @brief Sets the tag to the context handle.
+ *
+ * @param[in] context The context handle
+ * @param[in] tag The tag
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_context_get_tag()
+ */
+int <PREFIX>_<NAME>_context_set_tag(<PREFIX>_<NAME>_context_h context, void *tag);
 
-const char CB_INTERFACE_CONTEXT_SET_TAG[] =
-R"__c_cb(
-int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void *tag);
-)__c_cb";
+/**
+ * @brief Gets the tag from the context handle.
+ *
+ * @param[in] context The context handle
+ * @param[out] tag The tag
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_context_set_tag()
+ */
+int <PREFIX>_<NAME>_context_get_tag(<PREFIX>_<NAME>_context_h context, void **tag);
 
-const char CB_INTERFACE_CONTEXT_GET_TAG[] =
-R"__c_cb(
-int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void **tag);
-)__c_cb";
+/**
+ * @brief Gets the sender ID from the context handle.
+ * @details The @a sender should be released using free().
+ *
+ * @param[in] context The context handle
+ * @param[out] sender The sender ID of the context handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int <PREFIX>_<NAME>_context_get_sender(<PREFIX>_<NAME>_context_h context, char **sender);
 
-const char CB_INTERFACE_CONTEXT_GET_SENDER[] =
-R"__c_cb(
-int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char **sender);
+/**
+ * @brief Gets the instance ID from the context handle.
+ * @details The @a instance should be released using free().
+ *
+ * @param[in] context The context handle
+ * @param[out] instance The instance ID of the context handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int <PREFIX>_<NAME>_context_get_instance(<PREFIX>_<NAME>_context_h context, char **instance);
 )__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_DECL[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate of the interface.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_HANDLE[] =
 R"__c_cb(
-typedef struct ##_s *rpc_port_##_h;
+/**
+ * @brief The <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ */
+typedef struct <PREFIX>_<NAME>_<DELEGATE_NAME>_s *<PREFIX>_<NAME>_<DELEGATE_NAME>_h;
 )__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_DTOR[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <DELEGATE_NAME> The name of the delegate.
+ * <DELEGATE_PARAMS> The parameters of the callback function.
+ */
+constexpr const char CB_INTERFACE_DELEGATE_BASE[] =
 R"__c_cb(
-int rpc_port_##_destroy(rpc_port_##_h h);
-)__c_cb";
+/**
+ * @brief Creates a <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[out] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_create(<PREFIX>_<NAME>_<DELEGATE_NAME>_h *h);
 
-const char CB_INTERFACE_DELEGATOR_CLONER[] =
-R"__c_cb(
-int rpc_port_##_clone(rpc_port_##_h h, rpc_port_##_h *clone);
+/**
+ * @brief Destroys the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_clone()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h);
+
+/**
+ * @brief Creates and returns a copy of the given <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @remarks A new created <PREFIX>_<NAME>_<DELEGATE_NAME> should be released using
+ *          the <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy() if it's no longer needed.
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] clone If successful, a new created <PREFIX>_<NAME>_<DELEGATE_NAME> handle will be returned
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_<DELEGATE_NAME>_destroy()
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_clone(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, <PREFIX>_<NAME>_<DELEGATE_NAME>_h *clone);
+
+/**
+ * @brief Gets the ID of the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] id The ID
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *id);
+
+/**
+ * @brief Gets the sequence ID of the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] seq_id The Sequence ID
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_seq_id(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, int *seq_id);
+
+/**
+ * @brief Checks whether the delegate is for one-time or not.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] once The flag, it's true, the handle is for one-time
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_is_once(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, bool *once);
+
+/**
+ * @brief Gets the tag from the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @remarks The @a tag should be released using free().
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[out] tag The tag
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_get_tag(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h, char **tag);
+
+/**
+ * @brief Invokes the callback function of the <PREFIX>_<NAME>_<DELEGATE_NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME>_<DELEGATE_NAME> handle
+ * @param[in] ...
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #RPC_PORT_ERROR_IO_ERROR I/O error
+ */
+int <PREFIX>_<NAME>_<DELEGATE_NAME>_invoke(<PREFIX>_<NAME>_<DELEGATE_NAME>_h h<DELEGATE_PARAMS>);
 )__c_cb";
 
-const char CB_INTERFACE_DELEGATOR_INVOKER[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_CALLBACK_BASE[] =
 R"__c_cb(
-int rpc_port_##_invoke(rpc_port_##_h h$$);
+/**
+ * @brief Called when the proxy is connected.
+ * @details The callback function is called when the proxy is connected to the stub.
+ *
+ * @param[in] context The context handle
+ * @param[in] user_data The user data passed from the registration function
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_create_cb)(<PREFIX>_<NAME>_context_h context, void *user_data);
+
+/**
+ * @brief Called when the proxy is disconnected.
+ * @details The callback function is called when the proxy is disconnected from the stub.
+ *
+ * @param[in] context The context handle
+ * @param[in] user_data The user data passed from the registration function
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_terminate_cb)(<PREFIX>_<NAME>_context_h context, void *user_data);
+
+/**
+ * @brief Called to get the proxy context once for each connected proxy.
+ *
+ * @param[in] context The context handle
+ * @param[in] user_data The user data passed from the registration function
+ * @return @c true to continue with the next iteration of the loop,
+ *         otherwise @c false to break out of the loop
+ * @pre <PREFIX>_<NAME>_foreach_context() will invoke this callback.
+ * @see <PREFIX>_<NAME>_foreach_context()
+ */
+typedef bool (*<PREFIX>_<NAME>_context_cb)(<PREFIX>_<NAME>_context_h context, void *user_data);
 )__c_cb";
 
-const char CB_INTERFACE_REGISTER[] =
+/**
+ * <RETURN_TYPE> The return type of the method.
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_NAME> The name of the method of the interface.
+ * <METHOD_PARAMS> The parameters of the method.
+ */
+constexpr const char CB_INTERFACE_METHOD_CALLBACK_BASE[] =
 R"__c_cb(
-int rpc_port_stub_##_register(rpc_port_stub_##_callback_s *callback, void *user_data);
+/**
+ * @brief Called when the request of the proxy is delivered.
+ *
+ * @param[in] context The context handle
+ * @param[in] user_data The user data passed from the registration function
+ * @see #<PREFIX>_<NAME>_callback_s;
+ */
+typedef <RETURN_TYPE> (*<PREFIX>_<NAME>_<METHOD_NAME>_cb)(<PREFIX>_<NAME>_context_h context<METHOD_PARAMS>, void *user_data);
 )__c_cb";
 
-const char CB_INTERFACE_UNREGISTER[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_CALLBACK_DECLS> The declarations of the method callback functions.
+ */
+constexpr const char CB_INTERFACE_BASE[] =
 R"__c_cb(
-int rpc_port_stub_##_unregister(void);
+/**
+ * @brief The structure type containing the set of callback functions for handling stub events.
+ * @details It is one of the input parameters of the <PREFIX>_<NAME>_register() function.
+ *
+ * @see <PREFIX>_<NAME>_create_cb
+ * @see <PREFIX>_<NAME>_terminate_cb
+ */
+typedef struct {
+  <PREFIX>_<NAME>_create_cb create;  /**< This callback function is invoked when the proxy is connected. */
+  <PREFIX>_<NAME>_terminate_cb terminate;  /**< This callback function is invoked when the proxy is disconnected. */
+  <METHOD_CALLBACK_DECLS>
+} <PREFIX>_<NAME>_callback_s;
+
+/**
+ * @brief Registers the set of the callback functions and the port.
+ * @details This function registers the set of the callback functions to handle stub events.
+ *          And, the rpc_port_stub_listen() is called internally to handle events.
+ *
+ * @param[in] callback The set of callback functions to handle stub events
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #RPC_PORT_ERROR_IO_ERROR I/O error
+ * @retval #RPC_PORT_ERROR_PERMISSION_DENIED Permission denied
+ * @see <PREFIX>_<NAME>_unregister()
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+int <PREFIX>_<NAME>_register(<PREFIX>_<NAME>_callback_s *callback, void *user_data);
+
+/**
+ * @brief Unregisters the registered port.
+ */
+int <PREFIX>_<NAME>_unregister(void);
+
+/**
+ * @brief Retrieves the connected context handles.
+ *
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_context_cb()
+ */
+int <PREFIX>_<NAME>_foreach_context(<PREFIX>_<NAME>_context_cb callback, void *user_data);
+
+/**
+ * @brief Gets the number of connected clients.
+ *
+ * @param[out] client_number The client number
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_get_client_number(unsigned int *client_number);
 )__c_cb";
 
-const char CB_INTERFACE_CLIENT_NUMBER_GETTER[] =
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ * <METHOD_NAME> The name of the method of the interface.
+ */
+constexpr const char CB_INTERFACE_METHOD_CALLBACK_DECL[] =
 R"__c_cb(
-int rpc_port_stub_##_get_client_number(unsigned int *n);
+<PREFIX>_<NAME>_<METHOD_NAME>_cb <METHOD_NAME>;  /**< This callback function is invoked when the <METHOD_NAME> request is delivered. */
 )__c_cb";
 
 #endif  // IDLC_C_GEN_C_STUB_HEADER_GEN_CB_H_
index 249b594..a1706ed 100644 (file)
@@ -50,6 +50,14 @@ class Generator {
     return hasNamespace_;
   }
 
+  void EnableProxy(bool enable) {
+    isProxy_ = enable;
+  }
+
+  bool IsProxy() const {
+    return isProxy_;
+  }
+
   template<typename T, typename ...ARGS>
   void GenTemplate(std::string templ, std::ofstream& stream,
       T cb, ARGS... args) {
@@ -113,6 +121,7 @@ class Generator {
   std::shared_ptr<Document> doc_;
   std::ofstream out_file_;
   bool hasNamespace_ = true;
+  bool isProxy_ = true;
 };
 
 }  // namespace tidl
index 37f8aa1..206fc03 100644 (file)
@@ -55,9 +55,11 @@ void GenerateStubCodes(std::shared_ptr<tidl::Options> options,
     {
       tidl::CStubHeaderGen stub_header(ps.GetDoc());
       stub_header.EnableNamespace(options->HasNamespace());
+      stub_header.EnableProxy(false);
       stub_header.Run(options->GetOutput() + ".h");
       tidl::CStubBodyGen stub_body(ps.GetDoc(), options);
       stub_body.EnableNamespace(options->HasNamespace());
+      stub_body.EnableProxy(false);
       stub_body.Run(options->GetOutput() + ".c");
       break;
     }
@@ -108,9 +110,11 @@ void GenerateProxyCodes(std::shared_ptr<tidl::Options> options,
     {
       tidl::CProxyHeaderGen proxy_header(ps.GetDoc());
       proxy_header.EnableNamespace(options->HasNamespace());
+      proxy_header.EnableProxy(true);
       proxy_header.Run(options->GetOutput() + ".h");
-      tidl::CProxyBodyGen proxy_body(ps.GetDoc());
+      tidl::CProxyBodyGen proxy_body(ps.GetDoc(), options);
       proxy_body.EnableNamespace(options->HasNamespace());
+      proxy_body.EnableProxy(true);
       proxy_body.Run(options->GetOutput() + ".c");
       break;
     }