[cion] Implement C group generator 80/268580/6
authorjusung <jusung07.son@samsung.com>
Mon, 27 Dec 2021 07:30:59 +0000 (16:30 +0900)
committerjusung <jusung07.son@samsung.com>
Thu, 6 Jan 2022 01:40:55 +0000 (10:40 +0900)
Change-Id: Ice250308333c7a6769778eb1b3ecb779ca43a329
Signed-off-by: jusung <jusung07.son@samsung.com>
idlc/ast/parser.cc
idlc/ast/parser.h
idlc/ast/tidlc.yy
idlc/gen_cion/c_cion_group_body_gen.cc [new file with mode: 0644]
idlc/gen_cion/c_cion_group_body_gen.h [new file with mode: 0644]
idlc/gen_cion/c_cion_group_body_gen_cb.h [new file with mode: 0644]
idlc/gen_cion/c_cion_group_header_gen.cc [new file with mode: 0644]
idlc/gen_cion/c_cion_group_header_gen.h [new file with mode: 0644]
idlc/gen_cion/c_cion_group_header_gen_cb.h [new file with mode: 0644]
idlc/main.cc

index f28a11d..d2b6aa6 100644 (file)
@@ -33,9 +33,9 @@ void yylex_destroy(void*);
 
 namespace tidl {
 
-Parser::Parser(bool beta_enable, bool cion_enable)
+Parser::Parser(bool beta_enable, bool cion_enable, bool group_enable)
     : scanner_(nullptr), error_(false), beta_enable_(beta_enable),
-    cion_enable_(cion_enable) {
+    cion_enable_(cion_enable), group_enable_(group_enable) {
   yylex_init(&scanner_);
 }
 
@@ -86,4 +86,8 @@ bool Parser::IsCionEnabled() {
   return cion_enable_;
 }
 
+bool Parser::IsGroupEnabled() {
+  return group_enable_;
+}
+
 }  // namespace tidl
index fa8c1b0..69476eb 100644 (file)
@@ -27,7 +27,7 @@ namespace tidl {
 
 class Parser {
  public:
-  Parser(bool beta_enable = false, bool cion_enable = false);
+  Parser(bool beta_enable = false, bool cion_enable = false, bool group_enable = false);
   ~Parser();
 
   void* Scanner() const { return scanner_; }
@@ -38,6 +38,7 @@ class Parser {
   void ReportError(const std::string& err, unsigned line);
   bool IsBetaEnabled();
   bool IsCionEnabled();
+  bool IsGroupEnabled();
 
  private:
   void* scanner_;
@@ -46,6 +47,7 @@ class Parser {
   bool error_;
   bool beta_enable_;
   bool cion_enable_;
+  bool group_enable_;
 };
 
 }  // namespace tidl
index bab90b1..25c17fd 100644 (file)
@@ -287,9 +287,15 @@ declarations: declaration {
 ;
 
 declaration: base_type T_ID T_LEFT parameter_list T_RIGHT T_SEMICOLON {
-    $$ = new tidl::Declaration($2->ToString(), $1, $4, $1->GetComments(),
-        @1.begin.line, tidl::Declaration::MethodType::SYNC);
-    delete $2;
+    if (ps->IsGroupEnabled()) {
+      ps->ReportError("Group does not support 'sync' method type", @1.begin.line);
+      $$ = NULL;
+      delete $2;
+    } else {
+      $$ = new tidl::Declaration($2->ToString(), $1, $4, $1->GetComments(),
+          @1.begin.line, tidl::Declaration::MethodType::SYNC);
+      delete $2;
+    }
   }
   | T_VOID T_ID T_LEFT parameter_list T_RIGHT T_ASYNC T_SEMICOLON {
     $$ = new tidl::Declaration($2->ToString(),
@@ -299,12 +305,19 @@ declaration: base_type T_ID T_LEFT parameter_list T_RIGHT T_SEMICOLON {
     delete $2;
   }
   | T_VOID T_ID T_LEFT parameter_list T_RIGHT T_DELEGATE T_SEMICOLON {
-    $$ = new tidl::Declaration($2->ToString(),
-        new tidl::BaseType("void", $1->GetComments()), $4,
-        $1->GetComments(), @1.begin.line,
-        tidl::Declaration::MethodType::DELEGATE);
-    delete $1;
-    delete $2;
+    if (ps->IsGroupEnabled()) {
+      ps->ReportError("Group does not support 'delegate' method type", @1.begin.line);
+      $$ = NULL;
+      delete $1;
+      delete $2;
+    } else {
+      $$ = new tidl::Declaration($2->ToString(),
+          new tidl::BaseType("void", $1->GetComments()), $4,
+          $1->GetComments(), @1.begin.line,
+          tidl::Declaration::MethodType::DELEGATE);
+      delete $1;
+      delete $2;
+    }
   }
   | base_type T_ID T_LEFT parameter_list T_RIGHT T_ASYNC T_SEMICOLON {
     ps->ReportError("syntax error in method declaration.", @2.begin.line);
@@ -403,7 +416,11 @@ base_type: raw_type {
       $$ = $1;
     }
     | T_FILE {
-      if (!ps->IsBetaEnabled()) {
+      if (ps->IsGroupEnabled()) {
+        ps->ReportError("Group does not support 'file' type", @1.begin.line);
+        $$ = NULL;
+        delete $1;
+      } else if (!ps->IsBetaEnabled()) {
         ps->ReportError("syntax error. \"No identifier\".", @1.begin.line);
         ps->ReportError("try to use beta version (-b option).", @1.begin.line);
         $$ = NULL;
diff --git a/idlc/gen_cion/c_cion_group_body_gen.cc b/idlc/gen_cion/c_cion_group_body_gen.cc
new file mode 100644 (file)
index 0000000..63620aa
--- /dev/null
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+
+#include "idlc/gen_cion/c_cion_group_body_gen.h"
+#include "idlc/gen_cion/c_cion_group_body_gen_cb.h"
+
+namespace tidl {
+
+CCionGroupBodyGen::CCionGroupBodyGen(std::shared_ptr<Document> doc,
+    std::shared_ptr<Options> options)
+    : CCionBodyGeneratorBase(doc), options_(std::move(options)) {
+}
+
+void CCionGroupBodyGen::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  GenGNUSourceDefinition(stream);
+  GenIncludeDefaultHeaders(stream);
+  GenIncludeHeader(stream);
+  GenLogTag(stream, std::string("CION_GROUP"));
+  GenLogDefinition(stream);
+  GenBaseDefinition(stream);
+  GenInterfaceMethodHandlerType(stream);
+  GenInterfaceEnums(stream);
+  GenStructureDefs(stream);
+  GenInterfaceDefs(stream);
+  GenStructures(stream);
+  GenInterfaces(stream);
+}
+
+void CCionGroupBodyGen::OnFiniGen(std::ofstream& stream) {
+}
+
+void CCionGroupBodyGen::GenInterfaceDefs(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    const Interface &iface = static_cast<const Interface&>(*i);
+    GenInterfaceDef(stream, iface);
+  }
+}
+
+void CCionGroupBodyGen::GenInterfaceDef(std::ofstream& stream,
+    const Interface& iface) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE_DEF, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", iface.GetID());
+
+  stream << SmartIndent(code);
+}
+
+void CCionGroupBodyGen::GenInterfaceEnums(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& iface = static_cast<const Interface&>(*b);
+    GenInterfaceEnum(stream, iface);
+  }
+}
+
+// @see #CB_INTERFACE_METHOD_ENUM
+std::string CCionGroupBodyGen::GenMethodEnums(const Interface& iface) {
+  std::string method_enums, method_enum;
+
+  for (const auto& d : iface.GetDeclarations()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, {
+        { "<UPPERCASE_PREFIX>", GetHandlePrefix() },
+        { "<UPPERCASE_NAME>", iface.GetID() },
+        { "<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 CCionGroupBodyGen::GenInterfaceEnum(std::ofstream& stream,
+    const Interface& iface) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, {
+      { "<PREFIX>", GetHandlePrefix() },
+      { "<NAME>", iface.GetID() },
+      { "<METHOD_ENUMS>", GenMethodEnums(iface) }
+  });
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_HANDLER_TYPE
+void CCionGroupBodyGen::GenInterfaceMethodHandlerType(std::ofstream& stream) {
+  stream << SmartIndent(CB_INTERFACE_METHOD_HANDLER_TYPE);
+}
+
+void CCionGroupBodyGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    const Interface &iface = static_cast<const Interface&>(*i);
+    GenInterface(stream, iface);
+  }
+}
+
+void CCionGroupBodyGen::GenInterface(std::ofstream& stream, const Interface& iface) {
+  for (const auto& d : iface.GetDeclarations()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenInterfaceMethodHandlerBase(stream, iface, *d);
+  }
+
+  GenInterfaceMethodTable(stream, iface);
+
+  GenInterfaceBase(stream, iface);
+
+  for (const auto& d : iface.GetDeclarations()) {
+    if (d->GetMethodType() != Declaration::MethodType::ASYNC)
+      continue;
+
+    GenInterfaceMethodBase(stream, iface, *d);
+  }
+}
+
+// @see #CB_INTERFACE_METHOD_TABLE
+void CCionGroupBodyGen::GenInterfaceMethodTable(std::ofstream& stream,
+    const Interface& iface) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_TABLE, {
+      { "<NAME>", iface.GetID() },
+      { "<METHOD_HANDLERS>", GenMethodHandlers(iface) }
+  });
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_HANDLER
+std::string CCionGroupBodyGen::GenMethodHandlers(const Interface& iface) {
+  std::string code;
+  for (const auto& d : iface.GetDeclarations()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    std::string enum_value = GetHandlePrefix() + "_" + iface.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 },
+        { "<PREFIX>", GetHandlePrefix() },
+        { "<NAME>", iface.GetID() },
+        { "<METHOD_NAME>", d->GetID() }
+    });
+
+    code += RemoveLine(method_handler);
+  }
+
+  return code;
+}
+
+// @see #CB_INTERFACE_BASE
+void CCionGroupBodyGen::GenInterfaceBase(std::ofstream& stream,
+    const Interface& iface) {
+  std::string prefix = GetHandlePrefix();
+  std::string code = ReplaceAll(CB_INTERFACE_BASE, "<PREFIX>", prefix);
+  std::string name = iface.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);
+  std::string security = GenSecurityString(iface);
+  code = ReplaceAll(code, "<SET_SECURITY>", security);
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_HANDLER_BASE
+void CCionGroupBodyGen::GenInterfaceMethodHandlerBase(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_HANDLER_BASE, {
+      { "<PREFIX>", GetHandlePrefix() },
+      { "<NAME>", iface.GetID() },
+      { "<METHOD_NAME>", decl.GetID() },
+      { "<METHOD_HANDLER_ARGS_DECL>", GenMethodHandlerArgsDecl(iface, decl) },
+      { "<METHOD_HANDLER_PARCEL_READ>",
+          GenMethodHandlerParcelRead(iface, decl) },
+      { "<METHOD_HANDLER_CALLBACK_INVOKE>",
+          GenMethodHandlerCallbackInvoke(decl) },
+      { "<METHOD_HANDLER_ARGS_FREE>", GenMethodHandlerArgsFree(iface, decl) }
+  });
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_CALLBACK_INVOKE
+std::string CCionGroupBodyGen::GenMethodHandlerCallbackInvoke(
+    const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_INVOKE,
+      "<METHOD_NAME>", decl.GetID());
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC)
+    code = ReplaceAll(code, "<RES_SET>", "res_ = ");
+  else
+    code = ReplaceAll(code, "<RES_SET>", "");
+
+  std::string args;
+  for (const auto& p : decl.GetParameters()) {
+    args += ", ";
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::IN)
+      args += "&";
+
+    args += p->GetID();
+  }
+  code = ReplaceAll(code, "<METHOD_ARGS>", args);
+
+  return RemoveLine(code);
+}
+
+// @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 CCionGroupBodyGen::GenMethodHandlerParcelRead(const Interface& iface,
+    const Declaration& decl) {
+  std::string code;
+  for (const auto& p : decl.GetParameters()) {
+    std::string parcel_read_code;
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::IN)
+      continue;
+
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(iface, type)) {
+      parcel_read_code = ReplaceAll(
+          CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ, "<PREFIX>",
+          GetHandlePrefix());
+      parcel_read_code = ReplaceAll(parcel_read_code, "<NAME>",
+          GetFullNameFromType(type, iface));
+      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, iface));
+      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") {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ,
+          "<ARG>", p->GetID());
+    } else {
+      parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ,
+          "<PARCEL_TYPE>", GetParcelType(type));
+      parcel_read_code = ReplaceAll(parcel_read_code, "<ARG>", p->GetID());
+    }
+
+    code += parcel_read_code;
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CCionGroupBodyGen::GenMethodHandlerArgsDecl(const Interface& iface,
+    const Declaration& decl) {
+  std::string args_decl;
+  for (const auto& p : decl.GetParameters()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    args_decl += GetArgTypeString(type, iface) + p->GetID() + " = " +
+        GetErrorValue(type) + ";" + NLine(1);
+  }
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
+    args_decl += "rpc_port_parcel_h parcel_;" + NLine(1);
+    args_decl += GetArgTypeString(decl.GetType(), iface) + "res_ = " +
+        GetErrorValue(decl.GetType()) + ";" + NLine(1);
+  }
+
+  return args_decl;
+}
+
+// @see #CB_INTERFACE_METHOD_USER_DEFINED_FREE
+// @see #CB_INTERFACE_METHOD_BUNDLE_FREE
+// @see #CB_INTERFACE_METHOD_STRING_FREE
+std::string CCionGroupBodyGen::GenMethodHandlerArgsFree(const Interface& iface,
+    const Declaration& decl) {
+  std::string free_code;
+  std::string code;
+  for (const auto& p : decl.GetParameters()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(iface, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_FREE, {
+          { "<PREFIX>", GetHandlePrefix() },
+          { "<NAME>", GetFullNameFromType(type, iface) },
+          { "<ARG>", p->GetID() }
+      });
+    } else if (type.ToString() == "bundle") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_FREE,
+          "<ARG>", p->GetID());
+    } else if (type.ToString() == "string") {
+      free_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_FREE,
+          "<ARG>", p->GetID());
+    } else {
+      free_code.clear();
+    }
+
+    code += free_code;
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CCionGroupBodyGen::GenMethodParams(const Interface& iface,
+    const Declaration& decl) {
+  std::string params;
+  for (const auto& p : decl.GetParameters()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, iface) +
+        p->GetID();
+  }
+
+  return params;
+}
+
+std::string CCionGroupBodyGen::GenMethodParamsCheck(const Interface& iface,
+    const Declaration& decl) {
+  std::string params_check;
+  for (const auto& p : decl.GetParameters()) {
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(iface, type) ||
+        type.IsUserDefinedType() ||
+        type.ToString() == "list" ||
+        type.ToString() == "array" ||
+        type.ToString() == "bundle" ||
+        type.ToString() == "string")
+      params_check += " || " + p->GetID() + " == nullptr";
+  }
+
+  return params_check;
+}
+
+// @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 CCionGroupBodyGen::GenMethodParcelWrite(const Interface& iface,
+    const Declaration& decl) {
+  std::string code;
+  for (const auto& p : decl.GetParameters()) {
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::IN)
+      continue;
+
+    std::string parcel_write_code;
+    auto& type = param_type.GetBaseType();
+    if (IsDelegateType(iface, 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, iface);
+    } 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 {
+      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 RemoveLine(code);
+}
+
+// @see #CB_INTERFACE_METHOD_ASYNC_BASE
+std::string CCionGroupBodyGen::GenMethodAsyncBase(const Interface& iface,
+    const Declaration& decl) {
+  std::string prefix = GetHandlePrefix();
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_ASYNC_BASE, "<PREFIX>",
+      prefix);
+  std::string name = iface.GetID();
+  code = ReplaceAll(code, "<NAME>", name);
+  std::string method_name = decl.GetID();
+  code = ReplaceAll(code, "<METHOD_NAME>", method_name);
+  std::string args = GenMethodParams(iface, decl);
+  code = ReplaceAll(code, "<METHOD_PARAMS>", args);
+  std::string args_check = GenMethodParamsCheck(iface, 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(iface, decl);
+  code = ReplaceAll(code, "<METHOD_PARCEL_WRITE>", parcel_write);
+  return code;
+}
+
+std::string CCionGroupBodyGen::GenMethodArgs(const Interface& iface,
+    const Declaration& decl) {
+  std::string args_code;
+  for (const auto& p : decl.GetParameters()) {
+    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 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 CCionGroupBodyGen::GenMethodParcelReadBase(const Interface& iface,
+    const BaseType& type, const std::string& param_name) {
+  std::string parcel_read_code;
+  if (IsDelegateType(iface, 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, iface);
+      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") {
+      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 CCionGroupBodyGen::GenMethodParcelRead(const Interface& iface,
+    const Declaration& decl) {
+  std::string code;
+  std::string parcel_read_code;
+  for (const auto& p : decl.GetParameters()) {
+    auto& param_type = p->GetParameterType();
+    if (param_type.GetDirection() != ParameterType::Direction::OUT)
+      continue;
+
+    auto& type = param_type.GetBaseType();
+    code += GenMethodParcelReadBase(iface, type, "new_" + p->GetID());
+    code += ReplaceAll(CB_INTERFACE_METHOD_PARAM_SET, "<PARAM>",
+        p->GetID());
+  }
+
+  // Return Value
+  auto& base_type = decl.GetType();
+  code += GenMethodParcelReadBase(iface, base_type, "ret_");
+  return RemoveLine(code);
+}
+
+void CCionGroupBodyGen::GenInterfaceMethodBase(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl) {
+  std::string code = GenMethodAsyncBase(iface, decl);
+  stream << SmartIndent(code);
+}
+
+}  // namespace tidl
diff --git a/idlc/gen_cion/c_cion_group_body_gen.h b/idlc/gen_cion/c_cion_group_body_gen.h
new file mode 100644 (file)
index 0000000..326e62f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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_CION_GEN_C_GROUP_BODY_GEN_H_
+#define IDLC_C_CION_GEN_C_GROUP_BODY_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen_cion/c_cion_body_gen_base.h"
+#include "idlc/options.h"
+
+namespace tidl {
+
+class CCionGroupBodyGen : public CCionBodyGeneratorBase {
+ public:
+  explicit CCionGroupBodyGen(std::shared_ptr<Document> doc,
+      std::shared_ptr<Options> options);
+  virtual ~CCionGroupBodyGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenInterfaceDefs(std::ofstream& stream);
+  void GenInterfaceDef(std::ofstream& stream, const Interface& iface);
+  void GenInterfaceMethodHandlerType(std::ofstream& stream);
+  void GenInterfaceMethodHandlerBase(std::ofstream& stream,
+      const Interface& iface, const Declaration& decl);
+  std::string GenMethodHandlerArgsDecl(const Interface& iface,
+      const Declaration& decl);
+  std::string GenMethodHandlerArgsFree(const Interface& iface,
+      const Declaration& decl);
+  void GenInterfaceMethodTable(std::ofstream& stream,
+      const Interface& iface);
+  std::string GenMethodHandlerCallbackInvoke(const Declaration& decl);
+  std::string GenMethodHandlerParcelRead(const Interface& iface,
+    const Declaration& decl);
+  std::string GenMethodHandlers(const Interface& iface);
+  std::string GenMethodEnums(const Interface& iface);
+  void GenInterfaceEnums(std::ofstream& stream);
+  void GenInterfaceEnum(std::ofstream& stream, const Interface& iface);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenInterfaceBase(std::ofstream& stream, const Interface& iface);
+  void GenInterfaceMethodEnumBase(std::ofstream& stream, const Interface& iface);
+  void GenInterfaceMethodBase(std::ofstream& stream, const Interface& iface,
+      const Declaration& decl);
+
+  std::string GenMethodAsyncBase(const Interface& iface, const Declaration& decl);
+  std::string GenMethodParams(const Interface& iface, const Declaration& decl);
+  std::string GenMethodParamsCheck(const Interface& iface,
+      const Declaration& decl);
+  bool GenMethodParamsFileCheck(const Interface& iface,
+      const Declaration& decl);
+  std::string GenMethodParcelWrite(const Interface& iface,
+      const Declaration& decl);
+  std::string GenMethodArgs(const Interface& iface, const Declaration& decl);
+  std::string GenMethodParcelReadBase(const Interface& iface,
+      const BaseType& type, const std::string& param_name);
+  std::string GenMethodParcelRead(const Interface& iface,
+      const Declaration& decl);
+
+  private:
+    std::shared_ptr<Options> options_;
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_C_CION_GEN_C_GROUP_BODY_GEN_H_
\ No newline at end of file
diff --git a/idlc/gen_cion/c_cion_group_body_gen_cb.h b/idlc/gen_cion/c_cion_group_body_gen_cb.h
new file mode 100644 (file)
index 0000000..06fae16
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * 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_CION_GEN_C_GROUP_BODY_GEN_CB_H_
+#define IDLC_C_CION_GEN_C_GROUP_BODY_GEN_CB_H_
+
+
+constexpr const char CB_INTERFACE_METHOD_HANDLER_TYPE[] =
+R"__c_cb(
+typedef int (*cion_group_method_handler)(const cion_peer_info_h peer_info, rpc_port_parcel_h parcel, void *data);
+)__c_cb";
+
+/**
+ * <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";
+
+
+/**
+ * <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";
+
+
+
+/**
+ * <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;
+  int id;
+  int seq_id;
+  bool once;
+  <PREFIX>_<NAME>_<DELEGATE_NAME>_cb callback;
+  void *user_data;
+} <PREFIX>_<NAME>_<DELEGATE_NAME>_t;
+)__c_cb";
+
+/**
+ * <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";
+
+/**
+ * <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 {
+  char *topic_name;
+  cion_group_h group;
+  cion_security_h security;
+  <PREFIX>_<NAME>_callback_s callback;
+  GRecMutex mutex;
+  void *user_data;
+} <PREFIX>_<NAME>_t;
+)__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(const cion_peer_info_h peer_info, rpc_port_parcel_h parcel, void *user_data)
+{
+  <PREFIX>_<NAME>_t *h = user_data;
+  int ret_ = CION_ERROR_NONE;
+
+  <METHOD_HANDLER_ARGS_DECL>
+  if (h == nullptr || h->group == nullptr) {
+    _E("Invalid parameter");
+    ret_ = CION_ERROR_INVALID_PARAMETER;
+    goto out;
+  }
+  <METHOD_HANDLER_PARCEL_READ>
+  <METHOD_HANDLER_CALLBACK_INVOKE>
+
+ out:
+  <METHOD_HANDLER_ARGS_FREE>
+  return ret_;
+}
+)__c_cb";
+
+
+/**
+ * <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 int __<PREFIX>_<NAME>_process_received_event(<PREFIX>_<NAME>_t *h, const cion_peer_info_h peer_info, rpc_port_parcel_h parcel)
+{
+  int ret = CION_ERROR_NONE;
+  int cmd = -1;
+
+  rpc_port_parcel_read_int32(parcel, &cmd);
+  if (cmd >= 0 && cmd < ARRAY_SIZE(__<NAME>_method_table)) {
+    if (__<NAME>_method_table[cmd])
+      ret = __<NAME>_method_table[cmd](peer_info, parcel, h);
+  } else {
+    _W("Invalid protocol. cmd(%d)", cmd);
+    ret = CION_ERROR_INVALID_PARAMETER;
+  }
+
+  return ret;
+}
+
+static void __<PREFIX>_<NAME>_joined_cb(const char *topic_name,
+               const cion_peer_info_h peer_info, void *user_data)
+{
+  <PREFIX>_<NAME>_h h = user_data;
+
+  _I("topic_name(%s)", topic_name);
+  h->callback.joined(h, peer_info, h->user_data);
+}
+
+static void __<PREFIX>_<NAME>_left_cb(const char *topic_name,
+    const cion_peer_info_h peer_info, void *user_data)
+{
+  <PREFIX>_<NAME>_h h = user_data;
+
+  _W("topic_name(%s)", topic_name);
+  h->callback.left(h, peer_info, h->user_data);
+
+}
+
+static void __<PREFIX>_<NAME>_received(const char *topic_name,
+    const cion_peer_info_h peer_info, cion_payload_h payload, void *user_data)
+{
+  <PREFIX>_<NAME>_h h = user_data;
+  rpc_port_parcel_h parcel;
+  unsigned char *data;
+  cion_payload_type_e type;
+  int ret;
+  unsigned int data_len;
+
+  _W("topic_name(%s)", topic_name);
+
+  ret = cion_payload_get_type(payload, &type);
+  if (ret != CION_ERROR_NONE || type != CION_PAYLOAD_TYPE_DATA) {
+    _E("Faled to cion_payload_get_type : [%d][%d]", ret, type);
+    return;
+  }
+
+  ret = cion_payload_get_data(payload, &data, &data_len);
+  if (ret != CION_ERROR_NONE) {
+     _E("Faled to cion_payload_get_data : %d", ret);
+     return;
+   }
+
+  ret = rpc_port_parcel_create_from_raw(&parcel, data, data_len);
+  free(data);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create parcel handle from data. error(%d)", ret);
+    return;
+  }
+
+    __<PREFIX>_<NAME>_process_received_event(h, peer_info, parcel);
+    rpc_port_parcel_destroy(parcel);
+
+}
+
+int <PREFIX>_<NAME>_create(const char *topic_name, <PREFIX>_<NAME>_callback_s *callback, void *user_data, <PREFIX>_<NAME>_h *h)
+{
+  <PREFIX>_<NAME>_t *handle;
+  int ret;
+  cion_security_h security;
+
+  if (topic_name == nullptr || callback == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    return CION_ERROR_INVALID_PARAMETER;
+  }
+
+  if (callback->joined == nullptr || callback->left == nullptr) {
+    _E("Invalid parameter");
+    return CION_ERROR_INVALID_PARAMETER;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return CION_ERROR_OUT_OF_MEMORY;
+  }
+
+  g_rec_mutex_init(&handle->mutex);
+
+  handle->topic_name = strdup(topic_name);
+  if (handle->topic_name == nullptr) {
+    _E("Failed to duplicate topic name");
+    <PREFIX>_<NAME>_destroy(handle);
+    return CION_ERROR_OUT_OF_MEMORY;
+  }
+
+  ret = cion_security_create(&security);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to create security handle. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  <SET_SECURITY>
+  handle->security = security;
+
+  ret = cion_group_create(&handle->group, topic_name, handle->security);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to create group handle. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  handle->callback = *callback;
+  handle->user_data = user_data;
+
+  ret = cion_group_add_joined_cb(handle->group, __<PREFIX>_<NAME>_joined_cb, handle);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to add connection result cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  ret = cion_group_add_left_cb(handle->group, __<PREFIX>_<NAME>_left_cb, handle);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to add disconnected event cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  ret = cion_group_add_payload_received_cb(handle->group, __<PREFIX>_<NAME>_received, handle);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to add received event cb. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  ret = cion_group_subscribe(handle->group);
+  if (ret != CION_ERROR_NONE) {
+    _E("Failed to subscribe event. error(%d)", ret);
+    <PREFIX>_<NAME>_destroy(handle);
+    return ret;
+  }
+
+  *h = handle;
+
+  return CION_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h)
+{
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return CION_ERROR_INVALID_PARAMETER;
+  }
+
+  g_rec_mutex_lock(&h->mutex);
+  g_rec_mutex_unlock(&h->mutex);
+  g_rec_mutex_clear(&h->mutex);
+
+  if (h->group) {
+    cion_group_unsubscribe(h->group);
+    cion_group_destroy(h->group);
+  }
+
+  if (h->security)
+    cion_security_destroy(h->security);
+
+  if (h->topic_name)
+    free(h->topic_name);
+
+  free(h);
+
+  return CION_ERROR_NONE;
+}
+)__c_cb";
+
+/**
+ * <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_ = nullptr;
+  int res_;
+  unsigned int data_size_;
+  unsigned char *data_;
+  cion_payload_h pl_ = nullptr;
+
+  if (h == nullptr<METHOD_PARAMS_CHECK>) {
+    _E("Invalid parameter");
+    set_last_result(CION_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  g_rec_mutex_lock(&h->mutex);
+  if (h->group == nullptr) {
+    _E("Not connected");
+    g_rec_mutex_unlock(&h->mutex);
+    set_last_result(CION_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  res_ = rpc_port_parcel_create(&parcel_);
+  if (res_ != CION_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>
+
+  res_ = rpc_port_parcel_get_raw(parcel_, (void **)&data_, &data_size_);
+  if (res_ != RPC_PORT_ERROR_NONE) {
+    _E("Failed to get raw. error(%d)", res_);
+    goto out;
+  }
+
+  res_ = cion_payload_create(&pl_, CION_PAYLOAD_TYPE_DATA);
+  if (res_ != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_create : %d", res_);
+    goto out;
+  }
+
+  res_ = cion_payload_set_data(pl_, (const unsigned char*)data_, data_size_);
+  if (res_ != CION_ERROR_NONE) {
+    _E("Failed to cion_payload_set_data : %d", res_);
+    goto out;
+  }
+
+  res_ = cion_group_publish(h->group, pl_);
+  if (res_ != CION_ERROR_NONE) {
+    _E("Failed to cion_group_publish : %d", res_);
+    goto out;
+  }
+
+out:
+  cion_payload_destroy(pl_);
+  set_last_result(res_);
+  g_rec_mutex_unlock(&h->mutex);
+
+}
+)__c_cb";
+
+/**
+ * <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";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_bundle(parcel_, <ARG>);
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_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_METHOD_BASE_PARCEL_WRITE[] =
+R"__c_cb(
+rpc_port_parcel_write_<PARCEL_TYPE>(parcel_, <ARG>);
+)__c_cb";
+
+/**
+ * <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(
+<ARG> = nullptr;
+<PREFIX>_<NAME>_create(&<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to create handle");
+  ret_ = CION_ERROR_OUT_OF_MEMORY;
+  goto out;
+}
+
+rpc_port_parcel_read(parcel, &<ARG>->parcelable, <ARG>);
+if (get_last_result() != CION_ERROR_NONE) {
+  _E("Failed to read data");
+  <PREFIX>_<NAME>_destroy(<ARG>);
+  <ARG> = nullptr;
+  ret_ = get_last_result();
+  goto out;
+}
+)__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";
+
+/**
+ * <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(
+if (<ARG>)
+  <PREFIX>_<NAME>_destroy(<ARG>);
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_FREE[] =
+R"__c_cb(
+if (<ARG>)
+  bundle_free(<ARG>);
+)__c_cb";
+
+/**
+ * <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 (h->callback.<METHOD_NAME>)
+  <RES_SET>h->callback.<METHOD_NAME>(peer_info<METHOD_ARGS>, h->user_data);
+)__c_cb";
+
+
+/**
+ * <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(
+ret_ = <PREFIX>_<NAME>_create(&<ARG>);
+if (ret_ != CION_ERROR_NONE) {
+  _E("Failed to create handle. error(%d)", ret_);
+  goto out;
+}
+
+__<PREFIX>_<NAME>_set_peerInfo(<ARG>, peer_info);
+rpc_port_parcel_read(parcel, &<ARG>->parcelable, <ARG>);
+ret_ = get_last_result();
+if (ret_ != CION_ERROR_NONE) {
+  _E("Failed to read data. error(%d)", ret_);
+  goto out;
+}
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_FREE[] =
+R"__c_cb(
+if (<ARG>)
+  free(<ARG>);
+)__c_cb";
+
+/**
+ * <NAME> The name of the interface.
+ * <METHOD_HANDLERS> The declarations of method handlers.
+ */
+constexpr const char CB_INTERFACE_METHOD_TABLE[] =
+R"__c_cb(
+static cion_group_method_handler __<NAME>_method_table[] = {
+  <METHOD_HANDLERS>
+};
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ[] =
+R"__c_cb(
+<ARG> = nullptr;
+rpc_port_parcel_read_bundle(parcel, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  ret_ = CION_ERROR_OUT_OF_MEMORY;
+  goto out;
+
+}
+)__c_cb";
+
+/**
+ * <ARG> The argument.
+ */
+constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] =
+R"__c_cb(
+<ARG> = nullptr;
+rpc_port_parcel_read_string(parcel, &<ARG>);
+if (<ARG> == nullptr) {
+  _E("Failed to read data");
+  ret_ = CION_ERROR_OUT_OF_MEMORY;
+  goto out;
+}
+)__c_cb";
+
+/**
+ * <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";
+
+/**
+ * <PARAM> The name of the parameter.
+ */
+constexpr const char CB_INTERFACE_METHOD_PARAM_SET[] =
+R"__c_cb(
+*<PARAM> = new_<PARAM>;
+)__c_cb";
+
+#endif  // IDLC_C_CION_GEN_C_GROUP_BODY_GEN_CB_H_
diff --git a/idlc/gen_cion/c_cion_group_header_gen.cc b/idlc/gen_cion/c_cion_group_header_gen.cc
new file mode 100644 (file)
index 0000000..065aa0c
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "idlc/gen_cion/c_cion_group_header_gen.h"
+
+namespace {
+#include "idlc/gen_cion/c_cion_group_header_gen_cb.h"
+}
+
+namespace tidl {
+
+CCionGroupHeaderGen::CCionGroupHeaderGen(std::shared_ptr<Document> doc)
+    : CCionHeaderGeneratorBase(doc) {
+}
+
+void CCionGroupHeaderGen::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  GenPragmaOnce(stream);
+  GenIncludeDefaultHeaders(stream, false);
+  GenExplicitLinkageOpen(stream);
+  GenStructureHandles(stream);
+  GenInterfaceHandles(stream);
+  GenStructures(stream);
+  GenInterfaceCallbacks(stream);
+  GenInterfaces(stream);
+}
+
+void CCionGroupHeaderGen::OnFiniGen(std::ofstream& stream) {
+  GenExplicitLinkageClose(stream);
+}
+
+void CCionGroupHeaderGen::GenInterfaceHandles(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& iface = static_cast<const Interface&>(*b);
+    GenInterfaceHandle(stream, iface);
+  }
+}
+
+void CCionGroupHeaderGen::GenInterfaceCallbacks(std::ofstream& stream) {
+  for (auto& b : GetDocument().GetBlocks()) {
+    if (b->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    auto& iface = static_cast<const Interface&>(*b);
+    GenInterfaceCallbackBase(stream, iface);
+    for (const auto& d : iface.GetDeclarations()) {
+      if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+        continue;
+
+      GenInterfaceMethodCallbackBase(stream, iface, *d);
+    }
+  }
+}
+
+void CCionGroupHeaderGen::GenInterfaceCallbackBase(std::ofstream& stream,
+    const Interface& iface) {
+  std::string code = ReplaceAll(CB_INTERFACE_CALLBACK_BASE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", iface.GetID());
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_CALLBACK_BASE
+void CCionGroupHeaderGen::GenInterfaceMethodCallbackBase(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_BASE, {
+      { "<RETURN_TYPE>", GetReturnTypeString(decl.GetType()) },
+      { "<PREFIX>", GetHandlePrefix() },
+      { "<NAME>", iface.GetID() },
+      { "<METHOD_NAME>", decl.GetID() },
+      { "<METHOD_PARAMS>", GenMethodParams(iface, decl) }
+  });
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_HANDLE
+void CCionGroupHeaderGen::GenInterfaceHandle(std::ofstream& stream,
+    const Interface& iface) {
+  std::string code = ReplaceAll(CB_INTERFACE_HANDLE, "<PREFIX>",
+      GetHandlePrefix());
+  code = ReplaceAll(code, "<NAME>", iface.GetID());
+
+  stream << SmartIndent(code);
+}
+
+void CCionGroupHeaderGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    const Interface &iface = static_cast<const Interface&>(*i);
+    GenInterface(stream, iface);
+  }
+}
+
+void CCionGroupHeaderGen::GenInterface(std::ofstream& stream,
+    const Interface& iface) {
+
+  GenInterfaceBase(stream, iface);
+
+  for (const auto& d : iface.GetDeclarations()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    GenInterfaceMethodBase(stream, iface, *d);
+  }
+}
+
+// @see #CB_INTERFACE_BASE
+void CCionGroupHeaderGen::GenInterfaceBase(std::ofstream& stream,
+    const Interface& iface) {
+  std::string code = ReplaceAll(CB_INTERFACE_BASE, {
+      { "<PREFIX>", GetHandlePrefix() },
+      { "<NAME>", iface.GetID()},
+      { "<METHOD_CALLBACK_DECLS>", GenMethodCallbackDecls(iface) }
+  });
+
+  stream << SmartIndent(code);
+}
+
+// @see #CB_INTERFACE_METHOD_CALLBACK_DECL
+std::string CCionGroupHeaderGen::GenMethodCallbackDecls(const Interface& iface) {
+  std::string method_callback_decls;
+  for (const auto& d : iface.GetDeclarations()) {
+    if (d->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    std::string method_callback_decl = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_DECL, {
+        { "<PREFIX>", GetHandlePrefix() },
+        { "<NAME>", iface.GetID() },
+        { "<METHOD_NAME>", d->GetID() }
+    });
+
+    method_callback_decl = RemoveLine(method_callback_decl);
+    method_callback_decls += RemoveLine(method_callback_decl, 2);
+  }
+
+  return method_callback_decls;
+}
+
+std::string CCionGroupHeaderGen::GenMethodParams(const Interface& iface,
+    const Declaration& decl) {
+  std::string params;
+  for (const auto& p : decl.GetParameters()) {
+    params += ", ";
+    auto& param_type = p->GetParameterType();
+    auto& type = param_type.GetBaseType();
+    params += GetParamTypeString(param_type.GetDirection(), type, iface) +
+        p->GetID();
+  }
+
+  return params;
+}
+
+// @see #CB_INTERFACE_METHOD_BASE
+void CCionGroupHeaderGen::GenInterfaceMethodBase(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl) {
+  std::string code = ReplaceAll(CB_INTERFACE_METHOD_BASE, {
+      { "<RETURN_TYPE>", GetReturnTypeString(decl.GetType()) },
+      { "<PREFIX>", GetHandlePrefix() },
+      { "<NAME>", iface.GetID() },
+      { "<METHOD_NAME>", decl.GetID() },
+      { "<METHOD_PARAMS>", GenMethodParams(iface, decl) }
+  });
+
+  stream << SmartIndent(code);
+}
+
+}  // namespace tidl
diff --git a/idlc/gen_cion/c_cion_group_header_gen.h b/idlc/gen_cion/c_cion_group_header_gen.h
new file mode 100644 (file)
index 0000000..3661510
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDLC_C_CION_GEN_C_GROUP_HEADER_GEN_H_
+#define IDLC_C_CION_GEN_C_GROUP_HEADER_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen_cion/c_cion_header_gen_base.h"
+
+namespace tidl {
+
+class CCionGroupHeaderGen : public CCionHeaderGeneratorBase {
+ public:
+  explicit CCionGroupHeaderGen(std::shared_ptr<Document> doc);
+  virtual ~CCionGroupHeaderGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenInterfaceHandles(std::ofstream& stream);
+  void GenInterfaceHandle(std::ofstream& stream, const Interface& iface);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+
+  void GenInterfaceCallbacks(std::ofstream& stream);
+  void GenInterfaceCallbackBase(std::ofstream& stream, const Interface& iface);
+  void GenInterfaceMethodCallbackBase(std::ofstream& stream,
+      const Interface& iface, const Declaration& decl);
+  std::string GenMethodCallbackDecls(const Interface& iface);
+  void GenInterfaceBase(std::ofstream& stream, const Interface& iface);
+  void GenInterfaceMethodBase(std::ofstream& stream, const Interface& ifaceo,
+      const Declaration& decl);
+
+  std::string GenMethodParams(const Interface& iface, const Declaration& decl);
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_C_CION_GEN_C_GROUP_HEADER_GEN_H_
\ No newline at end of file
diff --git a/idlc/gen_cion/c_cion_group_header_gen_cb.h b/idlc/gen_cion/c_cion_group_header_gen_cb.h
new file mode 100644 (file)
index 0000000..75ee136
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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_CION_GEN_C_GROUP_HEADER_GEN_CB_H_
+#define IDLC_C_CION_GEN_C_GROUP_HEADER_GEN_CB_H_
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_HANDLE[] =
+R"__c_cb(
+/**
+ * @brief The <PREFIX>_<NAME> handle.
+ */
+typedef struct <PREFIX>_<NAME>_s *<PREFIX>_<NAME>_h;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_CALLBACK_BASE[] =
+R"__c_cb(
+/**
+ * @brief Called when a peer joins a topic.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] peer_info The Cion peer information handle \n
+ *            The @a peer_info can be used only in the callback. To use outside, make a copy.
+ * @param[in] user_data The user data
+ * @see cion_peer_info_clone()
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_joined_cb)(<PREFIX>_<NAME>_h h,
+               const cion_peer_info_h peer_info, void *user_data);
+
+/**
+ * @brief Called when a peer leaves a topic.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] peer_info The Cion peer information handle \n
+ *            The @a peer_info can be used only in the callback. To use outside, make a copy.
+ * @param[in] user_data The user data
+ * @see cion_peer_info_clone()
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+typedef void (*<PREFIX>_<NAME>_left_cb)(<PREFIX>_<NAME>_h h,
+               const cion_peer_info_h peer_info, void *user_data);
+
+)__c_cb";
+
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_BASE[] =
+R"__c_cb(
+/**
+ * @brief The structure type containing the set of callback functions for handling 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>_joined_cb joined;/**< This callback function is invoked when a peer joins a topic. */
+  <PREFIX>_<NAME>_left_cb left;/**< This callback function is invoked when when a peer leaves a topic. */
+  <METHOD_CALLBACK_DECLS>
+} <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.
+ *
+ * @privilege %http://tizen.org/privilege/d2d.datasharing
+ *            %http://tizen.org/privilege/internet
+ *
+ * @param[in] topic_name topic_name The name of topic
+ * @param[in] callback The set of callback functions to handle 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 #CION_ERROR_NONE Successful
+ * @retval #CION_ERROR_NOT_SUPPORTED Not supported
+ * @retval #CION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #CION_ERROR_PERMISSION_DENIED Permission denied
+
+ * @see <PREFIX>_<NAME>_destroy()
+ * @see #<PREFIX>_<NAME>_callback_s
+ */
+int <PREFIX>_<NAME>_create(const char *topic_name, <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 #CION_ERROR_NONE Successful
+ * @retval #CION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see <PREFIX>_<NAME>_create()
+ */
+int <PREFIX>_<NAME>_destroy(<PREFIX>_<NAME>_h h);
+
+)__c_cb";
+
+/**
+ * <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(
+/**
+ * @brief Called when the payload is received.
+ *
+ * @param[in] peer_info  The Cion peer information handle \n
+ *            The @a peer_info can be used only in the callback. To use outside, make a copy.
+ * @param[in] ...
+ * @param[in] user_data The user data passed from the registration function
+ * @see cion_peer_info_clone()
+ * @see #<PREFIX>_<NAME>_callback_s;
+ */
+typedef <RETURN_TYPE> (*<PREFIX>_<NAME>_<METHOD_NAME>_cb)(const cion_peer_info_h peer_info<METHOD_PARAMS>, void *user_data);
+)__c_cb";
+
+/**
+ * <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(
+<PREFIX>_<NAME>_<METHOD_NAME>_cb <METHOD_NAME>;  /**< This callback function is invoked when the <METHOD_NAME> request is delivered. */
+)__c_cb";
+
+/**
+ * <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(
+/**
+ * @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 #CION_ERROR_NONE Successful
+ * @exception #CION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @exception #CION_ERROR_OUT_OF_MEMORY Out of memory
+ * @exception #CION_ERROR_IO_ERROR I/O error
+ */
+<RETURN_TYPE><PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>);
+)__c_cb";
+
+#endif  // IDLC_C_CION_GEN_C_GROUP_HEADER_GEN_CB_H_
index 7a2c287..b4b68d2 100644 (file)
@@ -35,6 +35,8 @@
 #include "idlc/gen_cion/c_cion_proxy_body_gen.h"
 #include "idlc/gen_cion/c_cion_stub_header_gen.h"
 #include "idlc/gen_cion/c_cion_stub_body_gen.h"
+#include "idlc/gen_cion/c_cion_group_header_gen.h"
+#include "idlc/gen_cion/c_cion_group_body_gen.h"
 #include "idlc/gen_cion/cs_cion_proxy_gen.h"
 #include "idlc/gen_cion/cs_cion_stub_gen.h"
 #include "idlc/gen_cion/cpp_cion_proxy_header_gen.h"
@@ -237,18 +239,32 @@ void GenerateProxyCodes(std::shared_ptr<tidl::Options> options,
 
 void GenerateGroupCodes(std::shared_ptr<tidl::Options> options,
     tidl::Parser& ps) {
-  switch (options->GetLanguage()) {
-  case tidl::Options::LANGUAGE_TYPE_C:
-    break;
-  case tidl::Options::LANGUAGE_TYPE_CPP:
-    break;
-  case tidl::Options::LANGUAGE_TYPE_CSHARP:
-    break;
-  case tidl::Options::LANGUAGE_TYPE_JAVA:
-    break;
+  if (options->IsCion()) {
+    switch (options->GetLanguage()) {
+    case tidl::Options::LANGUAGE_TYPE_C:
+    {
 
-  default:
-    break;
+      tidl::CCionGroupHeaderGen group_header(ps.GetDoc());
+      group_header.EnableNamespace(options->HasNamespace());
+      group_header.SetType(static_cast<int>(options->GetType()));
+      group_header.Run(options->GetOutput() + ".h");
+
+      tidl::CCionGroupBodyGen group_body(ps.GetDoc(), options);
+      group_body.EnableNamespace(options->HasNamespace());
+      group_body.SetType(static_cast<int>(options->GetType()));
+      group_body.Run(options->GetOutput() + ".c");
+      break;
+    }
+    case tidl::Options::LANGUAGE_TYPE_CPP:
+      break;
+    case tidl::Options::LANGUAGE_TYPE_CSHARP:
+      break;
+    case tidl::Options::LANGUAGE_TYPE_JAVA:
+      break;
+
+    default:
+      break;
+  }
   }
 }
 
@@ -274,7 +290,8 @@ int main(int argc, char** argv) {
   if (!options)
     exit(1);
 
-  tidl::Parser ps(options->IsBetaEnabled(), options->IsCion());
+  tidl::Parser ps(options->IsBetaEnabled(), options->IsCion(),
+    options->GetType() == tidl::Options::Type::TYPE_GROUP ? true : false);
   std::string path(options->GetInput());
 
   if (!ps.ParseFromFile(path))