Support map & set container type 34/286234/24
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 2 Jan 2023 07:45:50 +0000 (07:45 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 13 Feb 2023 23:04:10 +0000 (23:04 +0000)
From protocol version 2, the map & set container types are supported.
The developer can define the map<K, V> and the set<K> in the tidl files.

Change-Id: I4195762b2fadaec5cdb7935390344c81f696e9f5
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
13 files changed:
idlc/ast/tidlc.ll
idlc/ast/tidlc.yy
idlc/ast/type.cc
idlc/ast/type.h
idlc/gen/c_gen_base.cc
idlc/gen/version2/c_body_generator_base.cc
idlc/gen/version2/c_body_generator_base.hh
idlc/gen/version2/c_body_generator_map_base_cb.hh [new file with mode: 0644]
idlc/gen/version2/c_body_generator_set_base_cb.hh [new file with mode: 0644]
idlc/gen/version2/c_header_generator_base.cc
idlc/gen/version2/c_header_generator_map_base_cb.hh [new file with mode: 0644]
idlc/gen/version2/c_header_generator_set_base_cb.hh [new file with mode: 0644]
idlc/gen/version2/c_proxy_body_generator_cb.hh

index b4faed0..4e2a8a1 100644 (file)
                           yylval->token = new tidl::Token(yytext, comments);
                           return yy::parser::token::T_ARRAY;
                         }
+"map"                   {
+                          yylval->token = new tidl::Token(yytext, comments);
+                          return yy::parser::token::T_MAP;
+                        }
+"set"                   {
+                          yylval->token = new tidl::Token(yytext, comments);
+                          return yy::parser::token::T_SET;
+                        }
 "struct"                {
                           yylval->token = new tidl::Token(yytext, comments);
                           return yy::parser::token::T_STRUCTURE;
index f83e5a4..80f2c12 100644 (file)
@@ -70,6 +70,8 @@ int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
 %token<token> T_BOOL
 %token<token> T_LIST
 %token<token> T_ARRAY
+%token<token> T_MAP
+%token<token> T_SET
 %token<token> T_VALUE
 %token<token> T_SB_OPEN
 %token<token> T_SB_CLOSE
@@ -528,9 +530,25 @@ raw_type: container_type {
 ;
 
 container_type: container_type_name T_META_OPEN base_type T_META_CLOSE {
-      $$ = new tidl::BaseType($1->ToString(), $1->GetComments());
-      $$->SetMetaType($3);
-      delete $1;
+      if ($1->ToString() == "map") {
+        ps->ReportError("syntax error. The value must be existed.", @1.begin.line);
+        delete $1;
+      } else {
+        $$ = new tidl::BaseType($1->ToString(), $1->GetComments());
+        $$->SetMetaType($3);
+        delete $1;
+      }
+    }
+    | container_type_name T_META_OPEN base_type T_COMMA base_type T_META_CLOSE {
+      if ($1->ToString() != "map") {
+        ps->ReportError("syntax error. The container type must be \"map\".", @1.begin.line);
+        delete $1;
+      } else {
+        $$ = new tidl::BaseType($1->ToString(), $1->GetComments());
+        $$->SetKeyType($3);
+        $$->SetValueType($5);
+        delete $1;
+      }
     }
 ;
 
@@ -542,6 +560,22 @@ container_type_name: T_LIST {
       $$ = new tidl::Token("array", $1->GetComments());
       delete $1;
     }
+    | T_MAP {
+      if (ps->GetVersion() < 2) {
+        ps->ReportError("syntax error. \"No identifier\".", @1.begin.line);
+        ps->ReportError("try to use protocol version 2.", @1.begin.line);
+      }
+      $$ = new tidl::Token("map", $1->GetComments());
+      delete $1;
+    }
+    | T_SET {
+      if (ps->GetVersion() < 2) {
+        ps->ReportError("syntax error. \"No identifier\".", @1.begin.line);
+        ps->ReportError("try to use protocol version 2.", @1.begin.line);
+      }
+      $$ = new tidl::Token("set", $1->GetComments());
+      delete $1;
+    }
 ;
 
 %%
index a4a3bec..adfcbd2 100644 (file)
@@ -33,15 +33,66 @@ BaseType::BaseType(std::string name, std::string comments,
 BaseType::BaseType(const BaseType& type)
   : Token(type.ToString(), type.GetComments()),
     user_defined_(type.IsUserDefinedType()) {
-  if (type.GetMetaType() != nullptr) {
+  if (type.GetMetaType() != nullptr)
     SetMetaType(new BaseType(*type.GetMetaType()));
-  }
+
+  if (type.GetKeyType() != nullptr)
+    SetKeyType(new BaseType(*type.GetKeyType()));
+
+  if (type.GetValueType() != nullptr)
+    SetValueType(new BaseType(*type.GetValueType()));
 }
 
 void BaseType::SetMetaType(BaseType* type) {
   meta_type_.reset(type);
 }
 
+const BaseType* BaseType::GetMetaType() const {
+  return meta_type_.get();
+}
+
+void BaseType::SetKeyType(BaseType* type) {
+  key_type_.reset(type);
+}
+
+const BaseType* BaseType::GetKeyType() const {
+  return key_type_.get();
+}
+
+void BaseType::SetValueType(BaseType* type) {
+  value_type_.reset(type);
+}
+
+const BaseType* BaseType::GetValueType() const {
+  return value_type_.get();
+}
+
+std::string BaseType::GetFullName(bool use_underbar) const {
+  std::string name = ToString();
+
+  if (meta_type_.get() != nullptr) {
+    name += use_underbar ? "_" : "<";
+    name += meta_type_->GetFullName(use_underbar);
+    name += use_underbar ? "" : ">";
+  } else if (key_type_.get() != nullptr) {
+    name += use_underbar ? "_" : "<";
+    name += key_type_->GetFullName(use_underbar);
+
+    if (value_type_.get() != nullptr) {
+      name += use_underbar ? "_" : ", ";
+      name += value_type_->GetFullName(use_underbar);
+    }
+
+    name += use_underbar ? "" : ">";
+  }
+
+  return name;
+}
+
+bool BaseType::IsUserDefinedType() const {
+  return user_defined_;
+}
+
 ParameterType::ParameterType(BaseType* type)
     : type_(type), dir_(Direction::IN) {
 }
index 77427ea..f148e93 100644 (file)
@@ -42,28 +42,21 @@ class BaseType : public Token {
   BaseType(const BaseType& type);
 
   void SetMetaType(BaseType* type);
-  const BaseType* GetMetaType() const {
-    return meta_type_.get();
-  }
+  const BaseType* GetMetaType() const;
 
-  std::string GetFullName() const {
-    std::string str = ToString();
+  void SetKeyType(BaseType* type);
+  const BaseType* GetKeyType() const;
 
-    if (meta_type_.get() != nullptr) {
-      str += "<";
-      str += meta_type_->GetFullName();
-      str += ">";
-    }
+  void SetValueType(BaseType* type);
+  const BaseType* GetValueType() const;
 
-    return str;
-  }
-
-  bool IsUserDefinedType() const {
-    return user_defined_;
-  }
+  std::string GetFullName(bool use_underbar = false) const;
+  bool IsUserDefinedType() const;
 
  private:
   std::unique_ptr<BaseType> meta_type_;
+  std::unique_ptr<BaseType> key_type_;
+  std::unique_ptr<BaseType> value_type_;
   bool user_defined_;
 };
 
index df2ac1a..39accc8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 - 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#include <ctime>
+#include "idlc/gen/c_gen_base.h"
+
+#include <algorithm>
 #include <cassert>
-#include <vector>
+#include <ctime>
 #include <sstream>
-#include <algorithm>
+#include <utility>
+#include <vector>
 
-#include "idlc/gen/c_gen_base.h"
+#include "idlc/gen/c_gen_base_cb.h"
 
+namespace tidl {
 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
+Structure* CreateStructure(std::string type_name, BaseType* key_type,
+    BaseType* value_type) {
+  if (key_type == nullptr || value_type == nullptr)
+    return nullptr;
+
+  auto* elms = new Elements();
+  if (elms == nullptr)
+    return nullptr;
+
+  elms->Add(
+      std::unique_ptr<Element>(
+         new Element(key_type->GetFullName(true), key_type, "", __LINE__)));
+  elms->Add(
+      std::unique_ptr<Element>(
+         new Element(value_type->GetFullName(true), value_type, "", __LINE__)));
+
+  auto* st = new Structure(std::move(type_name), elms, "", __LINE__);
+  if (st == nullptr) {
+    delete elms;
+    return nullptr;
+  }
 
-namespace tidl {
+  return st;
+}
+
+Structure* CreateStructure(std::string type_name, BaseType* elm_type) {
+  if (elm_type == nullptr)
+    return nullptr;
+
+  auto* elms = new Elements();
+  if (elms == nullptr)
+    return nullptr;
+
+  elms->Add(
+      std::unique_ptr<Element>(
+          new Element(elm_type->GetFullName(true), elm_type, "", __LINE__)));
+
+  auto* st = new Structure(
+      std::move(type_name), elms, "", __LINE__);
+  if (st == nullptr) {
+    delete elms;
+    return nullptr;
+  }
+
+  return st;
+}
+
+}  // namespace
 
 CGeneratorBase::CGeneratorBase(std::shared_ptr<Document> doc)
     : Generator(doc) {
@@ -68,14 +116,7 @@ std::string CGeneratorBase::NLine(int cnt) {
 }
 
 std::string CGeneratorBase::GetFullNameFromType(const BaseType& type) {
-  std::string str = type.ToString();
-
-  if (type.GetMetaType() != nullptr) {
-    str += "_";
-    str += GetFullNameFromType(*type.GetMetaType());
-  }
-
-  return str;
+  return type.GetFullName(true);
 }
 
 std::string CGeneratorBase::GetFullNameFromType(const BaseType& type,
@@ -89,6 +130,11 @@ std::string CGeneratorBase::GetFullNameFromType(const BaseType& type,
   if (type.GetMetaType() != nullptr) {
     str += "_";
     str += GetFullNameFromType(*type.GetMetaType(), iface);
+  } else if (type.GetKeyType() != nullptr) {
+    str += "_";
+    str += GetFullNameFromType(*type.GetKeyType(), iface);
+    str += "_";
+    str += GetFullNameFromType(*type.GetValueType(), iface);
   }
 
   return str;
@@ -99,7 +145,7 @@ std::string CGeneratorBase::GetDataTypeString(const BaseType& type,
   if (type.IsUserDefinedType())
     return GetHandlePrefix() + "_" + type.ToString() + "_h ";
 
-  if (type.GetMetaType() != nullptr)
+  if (type.GetMetaType() != nullptr || type.GetKeyType() != nullptr)
     return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h ";
 
   if (type.ToString() == "string" || type.ToString() == "file")
@@ -118,32 +164,32 @@ std::string CGeneratorBase::GetReturnTypeString(const BaseType& type) {
   if (type.IsUserDefinedType())
     return GetHandlePrefix() + "_" + type.ToString() + "_h ";
 
-  if (type.GetMetaType() != nullptr)
+  if (type.GetMetaType() != nullptr || type.GetKeyType() != nullptr)
     return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h ";
 
   return type_map_[type.ToString()];
 }
 
 void CGeneratorBase::AddStructureFromType(const BaseType& type) {
-  if (type.GetMetaType() == nullptr)
+  auto* meta_type = type.GetMetaType();
+  auto* key_type = type.GetKeyType();
+  if (meta_type == nullptr && key_type == nullptr)
     return;
 
-  BaseType* t = new BaseType(*type.GetMetaType());
-  assert(t != nullptr);
-
+  Structure* st;
   std::string type_name = GetFullNameFromType(type);
-  auto elm = std::unique_ptr<Element>(new Element(type_name, t, "", __LINE__));
-  assert(elm != nullptr);
-
-  Elements* elms = new Elements();
-  assert(elms != nullptr);
-  elms->Add(std::move(elm));
-
-  auto* st = new Structure(type_name, elms, "", __LINE__);
+  if (meta_type != nullptr) {
+    AddStructureFromType(*meta_type);
+    st = CreateStructure(type_name, new BaseType(*meta_type));
+  } else {
+    AddStructureFromType(*key_type);
+    auto* value_type = type.GetValueType();
+    AddStructureFromType(*value_type);
+    st = CreateStructure(type_name, new BaseType(*key_type),
+        new BaseType(*value_type));
+  }
   assert(st != nullptr);
 
-  AddStructureFromType(*type.GetMetaType());
-
   if (StructureExist(st)) {
     delete st;
     return;
@@ -154,30 +200,25 @@ void CGeneratorBase::AddStructureFromType(const BaseType& type) {
 
 void CGeneratorBase::AddStructureFromType(const BaseType& type,
     const Interface& iface) {
-  if (type.GetMetaType() == nullptr)
+  auto* meta_type = type.GetMetaType();
+  auto* key_type = type.GetKeyType();
+  if (meta_type == nullptr && key_type == nullptr)
     return;
 
-  BaseType* t = nullptr;
-  if (IsDelegateType(iface, *type.GetMetaType()))
-    t = new BaseType(GetFullNameFromType(*type.GetMetaType(), iface), "", true);
-  else
-    t = new BaseType(*type.GetMetaType());
-
-  assert(t != nullptr);
-
+  Structure* st;
   std::string type_name = GetFullNameFromType(type, iface);
-  auto elm = std::unique_ptr<Element>(new Element(type_name, t, "", __LINE__));
-  assert(elm != nullptr);
-
-  Elements* elms = new Elements();
-  assert(elms != nullptr);
-  elms->Add(std::move(elm));
-
-  auto* st = new Structure(type_name, elms, "", __LINE__);
+  if (meta_type != nullptr) {
+    AddStructureFromType(*meta_type, iface);
+    st = CreateStructure(type_name, new BaseType(*meta_type));
+  } else {
+    AddStructureFromType(*key_type, iface);
+    auto* value_type = type.GetValueType();
+    AddStructureFromType(*value_type);
+    st = CreateStructure(type_name, new BaseType(*key_type),
+        new BaseType(*value_type));
+  }
   assert(st != nullptr);
 
-  AddStructureFromType(*type.GetMetaType(), iface);
-
   if (StructureExist(st)) {
     delete st;
     return;
@@ -382,7 +423,9 @@ bool CGeneratorBase::StructureExist(const Structure* st) {
 
 std::string CGeneratorBase::GetParamTypeString(
     ParameterType::Direction direction, const BaseType& type) {
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     if (direction == ParameterType::Direction::IN)
       return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h ";
     else
@@ -405,7 +448,9 @@ std::string CGeneratorBase::GetParamTypeString(
 std::string CGeneratorBase::GetParamTypeString(
     ParameterType::Direction direction, const BaseType& type,
     const Interface& iface) {
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     if (direction == ParameterType::Direction::IN) {
       return GetHandlePrefix() + "_" + GetFullNameFromType(type, iface) + "_h ";
     } else {
@@ -429,7 +474,9 @@ std::string CGeneratorBase::GetParamTypeString(
 
 std::string CGeneratorBase::GetArgTypeString(const BaseType& type,
     const Interface& iface) {
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr)
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr)
     return GetHandlePrefix() + "_" + GetFullNameFromType(type, iface) + "_h ";
 
   return type_map_[type.ToString()];
@@ -438,6 +485,7 @@ std::string CGeneratorBase::GetArgTypeString(const BaseType& type,
 std::string CGeneratorBase::GetErrorValue(const BaseType& type) {
   if (type.IsUserDefinedType() ||
       type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr ||
       type.ToString() == "bundle" ||
       type.ToString() == "string"||
       type.ToString() == "file")
index 6683217..f6a7e42 100644 (file)
 
 #include <string.h>
 
+#include <utility>
+
 #include "idlc/gen/version2/c_body_generator_array_base_cb.hh"
 #include "idlc/gen/version2/c_body_generator_base_cb.hh"
 #include "idlc/gen/version2/c_body_generator_list_base_cb.hh"
+#include "idlc/gen/version2/c_body_generator_map_base_cb.hh"
+#include "idlc/gen/version2/c_body_generator_set_base_cb.hh"
 
 namespace tidl {
 namespace version2 {
+namespace {
+
+bool IsPtrType(const BaseType& type) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr ||
+      type.ToString() == "string" ||
+      type.ToString() == "bundle" ||
+      type.ToString() == "file")
+    return true;
+
+  return false;
+}
+
+}  // namespace
 
 CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr<Document> doc)
     : tidl::CBodyGeneratorBase(std::move(doc)) { }
@@ -76,10 +95,20 @@ void CBodyGeneratorBase::GenStructureListBaseDefinition(std::ofstream& stream,
 
 void CBodyGeneratorBase::GenStructureMapBaseDefinition(std::ofstream& stream,
     const Structure& st) {
+  ReplaceAll(CB_STRUCTURE_MAP_DEF)
+      .Change("<PREFIX>", GetHandlePrefix())
+      .Change("<NAME>", st.GetID())
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
 }
 
 void CBodyGeneratorBase::GenStructureSetBaseDefinition(std::ofstream& stream,
     const Structure& st) {
+  ReplaceAll(CB_STRUCTURE_SET_DEF)
+      .Change("<PREFIX>", GetHandlePrefix())
+      .Change("<NAME>", st.GetID())
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
 }
 
 std::string CBodyGeneratorBase::GenBaseElements(const Elements& elms) {
@@ -135,7 +164,9 @@ std::string CBodyGeneratorBase::GenArrayUnitMapWrite(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_UNIT_MAP_WRITE)
         .Change("<TYPE_NAME>", GetFullNameFromType(type));
   } else if (type.ToString() == "bundle") {
@@ -154,7 +185,9 @@ std::string CBodyGeneratorBase::GenArrayUnitMapRead(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_UNIT_MAP_READ)
         .Change("<TYPE_NAME>", GetFullNameFromType(type));
   } else if (type.ToString() == "bundle") {
@@ -173,7 +206,9 @@ std::string CBodyGeneratorBase::GenArrayElementsFree(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_FREE)
         .Change("<PREFIX>", GetHandlePrefix())
         .Change("<NAME>", GetFullNameFromType(type));
@@ -216,7 +251,9 @@ std::string CBodyGeneratorBase::GenListDataFree(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_FREE)
         .Change("<PREFIX>", GetHandlePrefix())
         .Change("<NAME>", GetFullNameFromType(type));
@@ -235,7 +272,9 @@ std::string CBodyGeneratorBase::GenListUnitMapWrite(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_UNIT_MAP_WRITE)
         .Change("<TYPE_NAME>", GetFullNameFromType(type));
   } else if (type.ToString() == "bundle") {
@@ -254,7 +293,9 @@ std::string CBodyGeneratorBase::GenListUnitMapRead(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_UNIT_MAP_READ)
         .Change("<TYPE_NAME>", GetFullNameFromType(type));
   } else if (type.ToString() == "bundle") {
@@ -276,7 +317,9 @@ std::string CBodyGeneratorBase::GenListAdd(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_ADD)
         .Change("<PREFIX>", GetHandlePrefix())
         .Change("<NAME>", GetFullNameFromType(type));
@@ -297,14 +340,10 @@ std::string CBodyGeneratorBase::GenListCallbackParamType(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() ||
-      type.GetMetaType() != nullptr ||
-      type.ToString() == "bundle" ||
-      type.ToString() == "string" ||
-      type.ToString() == "file")
+  if (IsPtrType(type))
     code = std::string("value");
   else
-    code = std::string ("*value");
+    code = std::string("*value");
 
   return code;
 }
@@ -329,19 +368,513 @@ void CBodyGeneratorBase::GenStructureListBase(std::ofstream& stream,
       .Out(stream);
 }
 
+std::string CBodyGeneratorBase::GenMapContains(const BaseType& key_type) {
+  std::string code;
+  if (IsPtrType(key_type))
+    code = CB_MAP_CONTAINS_KEY_PTR_TYPE;
+  else
+    code = CB_MAP_CONTAINS_KEY_BASE_TYPE;
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapKeyExistNullCheck(
+    const BaseType& key_type) {
+  std::string code;
+  if (IsPtrType(key_type))
+    code = CB_MAP_HANDLE_KEY_EXIST_NULL_CHECK;
+  else
+    code = CB_MAP_HANDLE_EXIST_NULL_CHECK;
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenMapForeachVarsDefinition(
+    const BaseType& key_type, const BaseType& value_type) {
+  std::string code;
+  bool is_key_ptr = IsPtrType(key_type);
+  bool is_value_ptr = IsPtrType(value_type);
+  if (is_key_ptr && is_value_ptr)
+    code = CB_MAP_FOREACH_VARS_DEF_KEY_PTR_VALUE_PTR_TYPE;
+  else if (is_key_ptr && !is_value_ptr)
+    code = CB_MAP_FOREACH_VARS_DEF_KEY_PTR_VALUE_BASE_TYPE;
+  else if (!is_key_ptr && is_value_ptr)
+    code = CB_MAP_FOREACH_VARS_DEF_KEY_BASE_VALUE_PTR_TYPE;
+  else
+    code = CB_MAP_FOREACH_VARS_DEF_KEY_BASE_VALUE_BASE_TYPE;
+
+  code = ReplaceAll(code)
+      .Change("<KEY_TYPE>",
+          RemoveLastSpaces(GetDataTypeString(key_type, false)))
+      .Change("<VALUE_TYPE>",
+          RemoveLastSpaces(GetDataTypeString(value_type, false)));
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapErase(const BaseType& key_type) {
+  std::string code;
+  if (IsPtrType(key_type))
+    code = CB_MAP_ERASE_KEY_PTR_TYPE;
+  else
+    code = CB_MAP_ERASE_KEY_BASE_TYPE;
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapKeyNullCheck(
+    const BaseType& key_type) {
+  std::string code;
+  if (IsPtrType(key_type))
+    code = CB_MAP_HANDLE_KEY_NULL_CHECK;
+  else
+    code = CB_MAP_HANDLE_NULL_CHECK;
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenMapLookupValueSet(
+    const BaseType& value_type) {
+  std::string code;
+  if (value_type.IsUserDefinedType() ||
+      value_type.GetMetaType() != nullptr ||
+      value_type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_MAP_LOOKUP_VALUE_USER_DEFINED_SET)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", value_type.GetFullName(true));
+  } else if (value_type.ToString() == "bundle") {
+    code = CB_MAP_LOOKUP_VALUE_BUNDLE_SET;
+  } else if (value_type.ToString() == "string") {
+    code = CB_MAP_LOOKUP_VALUE_STRING_SET;
+  } else {
+    code = ReplaceAll(CB_MAP_LOOKUP_VALUE_BASE_SET)
+        .Change("<VALUE_TYPE>",
+            RemoveLastSpaces(GetDataTypeString(value_type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapLookup(
+    const BaseType& key_type, const BaseType& value_type) {
+  std::string code;
+  if (IsPtrType(key_type)) {
+    code = ReplaceAll(CB_MAP_LOOKUP_KEY_PTR_TYPE)
+        .Change("<MAP_LOOKUP_VALUE_SET>", GenMapLookupValueSet(value_type));
+  } else {
+    code = ReplaceAll(CB_MAP_LOOKUP_KEY_BASE_TYPE)
+        .Change("<MAP_LOOKUP_VALUE_SET>", GenMapLookupValueSet(value_type));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapKeyValueNullCheck(
+    const BaseType& key_type) {
+  std::string code;
+  if (IsPtrType(key_type))
+    code = CB_MAP_HANDLE_KEY_VALUE_NULL_CHECK;
+  else
+    code = CB_MAP_HANDLE_VALUE_NULL_CHECK;
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenMapInsertNewKeyFree(
+    const BaseType& key_type) {
+  std::string code;
+  if (key_type.IsUserDefinedType() ||
+      key_type.GetMetaType() != nullptr ||
+      key_type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_MAP_INSERT_NEW_KEY_USER_DEFINED_FREE)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", key_type.GetFullName(true));
+  } else if (key_type.ToString() == "bundle") {
+    code = CB_MAP_INSERT_NEW_KEY_BUNDLE_FREE;
+  } else if (key_type.ToString() == "string" || key_type.ToString() == "file") {
+    code = CB_MAP_INSERT_NEW_KEY_STRING_FREE;
+  } else {
+    code = CB_MAP_INSERT_NEW_KEY_BASE_FREE;
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapInsertNewValueImpl(
+    const BaseType& key_type, const BaseType& value_type) {
+  std::string code;
+  if (value_type.IsUserDefinedType() ||
+      value_type.GetMetaType() != nullptr ||
+      value_type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_MAP_INSERT_NEW_VALUE_USER_DEFINED_IMPL)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", value_type.GetFullName(true));
+  } else if (value_type.ToString() == "bundle") {
+    code = CB_MAP_INSERT_NEW_VALUE_BUNDLE_IMPL;
+  } else if (value_type.ToString() == "string" ||
+      value_type.ToString() == "file") {
+    code = CB_MAP_INSERT_NEW_VALUE_STRING_IMPL;
+  } else {
+    code = ReplaceAll(CB_MAP_INSERT_NEW_VALUE_BASE_IMPL)
+        .Change("<VALUE_TYPE>",
+            RemoveLastSpaces(GetDataTypeString(value_type, false)));
+  }
+
+  code = ReplaceAll(code)
+      .Change("<MAP_INSERT_NEW_KEY_FREE>", GenMapInsertNewKeyFree(key_type));
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapInsertNewKeyImpl(
+    const BaseType& key_type) {
+  std::string code;
+  if (key_type.IsUserDefinedType() ||
+      key_type.GetMetaType() != nullptr ||
+      key_type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_MAP_INSERT_NEW_KEY_USER_DEFINED_IMPL)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", key_type.GetFullName(true));
+  } else if (key_type.ToString() == "bundle") {
+    code = CB_MAP_INSERT_NEW_KEY_BUNDLE_IMPL;
+  } else if (key_type.ToString() == "string" || key_type.ToString() == "file") {
+    code = CB_MAP_INSERT_NEW_KEY_STRING_IMPL;
+  } else {
+    code = ReplaceAll(CB_MAP_INSERT_NEW_KEY_BASE_IMPL)
+        .Change("<KEY_TYPE>",
+            RemoveLastSpaces(GetDataTypeString(key_type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapInsert(
+    const BaseType& key_type, const BaseType& value_type) {
+  std::string code;
+  code = ReplaceAll(CB_MAP_INSERT)
+      .Change("<MAP_INSERT_NEW_KEY_IMPL>", GenMapInsertNewKeyImpl(key_type))
+      .Change("<MAP_INSERT_NEW_VALUE_IMPL>",
+          GenMapInsertNewValueImpl(key_type, value_type));
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapKeyValueNullCheck(
+    const BaseType& key_type, const BaseType& value_type) {
+  std::string code;
+  bool is_key_ptr = IsPtrType(key_type);
+  bool is_value_ptr = IsPtrType(value_type);
+  if (is_key_ptr && is_value_ptr)
+    code = CB_MAP_HANDLE_KEY_VALUE_NULL_CHECK;
+  else if (is_key_ptr && !is_value_ptr)
+    code = CB_MAP_HANDLE_KEY_NULL_CHECK;
+  else if (!is_key_ptr && is_value_ptr)
+    code = CB_MAP_HANDLE_VALUE_NULL_CHECK;
+  else
+    code = CB_MAP_HANDLE_NULL_CHECK;
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenMapFreeFunc(
+    const BaseType& type) {
+  std::string code;
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_MAP_USER_DEFINED_FREE_FUNC)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", type.GetFullName(true));
+  } else if (type.ToString() == "bundle") {
+    code = CB_MAP_BUNDLE_FREE_FUNC;
+  } else {
+    code = CB_MAP_FREE_FUNC;
+  }
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenMapCompareKeyVarsDefinition(
+    const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type)) {
+    code = ReplaceAll(CB_MAP_COMPARE_KEY_VARS_DEF_PTR_TYPE)
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  } else {
+    code = ReplaceAll(CB_MAP_COMPARE_KEY_VARS_DEF_BASE_TYPE)
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapUnitMapValueRead(
+    const BaseType& type) {
+  std::string code;
+  code = ReplaceAll(CB_MAP_UNIT_MAP_VALUE_READ)
+      .Change("<VALUE>", type.GetFullName(true));
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapUnitMapKeyRead(
+    const BaseType& type) {
+  std::string code;
+  code = ReplaceAll(CB_MAP_UNIT_MAP_KEY_READ)
+      .Change("<KEY>", type.GetFullName(true));
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapUnitMapValueWrite(
+    const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type)) {
+    code = ReplaceAll(CB_MAP_UNIT_MAP_VALUE_WRITE_PTR_TYPE)
+        .Change("<VALUE>", type.GetFullName(true))
+        .Change("<VALUE_TYPE>",
+            RemoveLastSpaces(GetDataTypeString(type, false)));
+  } else {
+    code = ReplaceAll(CB_MAP_UNIT_MAP_VALUE_WRITE_BASE_TYPE)
+        .Change("<VALUE>", type.GetFullName(true))
+        .Change("<VALUE_TYPE>",
+            RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenMapUnitMapKeyWrite(
+    const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type)) {
+    code = ReplaceAll(CB_MAP_UNIT_MAP_KEY_WRITE_PTR_TYPE)
+        .Change("<KEY>", type.GetFullName(true))
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  } else {
+    code = ReplaceAll(CB_MAP_UNIT_MAP_KEY_WRITE_BASE_TYPE)
+        .Change("<KEY>", type.GetFullName(true))
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
 void CBodyGeneratorBase::GenStructureMapBase(std::ofstream& stream,
     const Structure& st) {
+  auto iter = st.GetElements().begin();
+  if (std::next(iter) == st.GetElements().end())
+    return;
+
+  auto& key_elm = *(iter);
+  auto& key_type = key_elm->GetType();
+  auto key_param_type = GetParamTypeString(ParameterType::Direction::IN,
+      key_type);
+  auto& value_elm = *(std::next(iter));
+  auto& value_type = value_elm->GetType();
+  auto value_param_type = GetParamTypeString(ParameterType::Direction::IN,
+      value_type);
+  auto value_param_type_out = GetParamTypeString(ParameterType::Direction::OUT,
+      value_type);
+
+  ReplaceAll(CB_STRUCTURE_MAP_BASE)
+      .Change("<PREFIX>", GetHandlePrefix())
+      .Change("<NAME>", st.GetID())
+      .Change("<KEY_TYPE>", GetDataTypeString(key_type, false))
+      .Change("<VALUE_TYPE>", GetDataTypeString(value_type, false))
+      .Change("<KEY_PARAM_TYPE>", key_param_type)
+      .Change("<VALUE_PARAM_TYPE>", value_param_type)
+      .Change("<VALUE_PARAM_TYPE_OUT>", value_param_type_out)
+      .Change("<MAP_UNIT_MAP_KEY_WRITE>", GenMapUnitMapKeyWrite(key_type))
+      .Change("<MAP_UNIT_MAP_VALUE_WRITE>", GenMapUnitMapValueWrite(value_type))
+      .Change("<MAP_UNIT_MAP_KEY_READ>", GenMapUnitMapKeyRead(key_type))
+      .Change("<MAP_UNIT_MAP_VALUE_READ>", GenMapUnitMapValueRead(value_type))
+      .Change("<MAP_COMPARE_KEY_VARS_DEF>",
+          GenMapCompareKeyVarsDefinition(key_type))
+      .Change("<MAP_KEY_FREE_FUNC>", GenMapFreeFunc(key_type))
+      .Change("<MAP_VALUE_FREE_FUNC>", GenMapFreeFunc(value_type))
+      .Change("<MAP_INSERT_ARGS_NULL_CHECK>",
+          GenMapKeyValueNullCheck(key_type, value_type))
+      .Change("<MAP_INSERT>", GenMapInsert(key_type, value_type))
+      .Change("<MAP_LOOKUP_ARGS_NULL_CHECK>",
+          GenMapKeyValueNullCheck(key_type))
+      .Change("<MAP_LOOKUP>", GenMapLookup(key_type, value_type))
+      .Change("<MAP_ERASE_ARGS_NULL_CHECK>", GenMapKeyNullCheck(key_type))
+      .Change("<MAP_ERASE>", GenMapErase(key_type))
+      .Change("<MAP_REPLACE_ARGS_NULL_CHECK>",
+          GenMapKeyValueNullCheck(key_type, value_type))
+      .Change("<MAP_FOREACH_VARS_DEF>",
+          GenMapForeachVarsDefinition(key_type, value_type))
+      .Change("<MAP_CONTAINS_ARGS_NULL_CHECK>",
+          GenMapKeyExistNullCheck(key_type))
+      .Change("<MAP_CONTAINS>", GenMapContains(key_type))
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
+}
+
+std::string CBodyGeneratorBase::GenSetContains(const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type))
+    code = CB_SET_CONTAINS_KEY_PTR_TYPE;
+  else
+    code = CB_SET_CONTAINS_KEY_BASE_TYPE;
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenSetKeyExistNullCheck(
+    const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type))
+    code = CB_SET_HANDLE_KEY_EXIST_NULL_CHECK;
+  else
+    code = CB_SET_HANDLE_EXIST_NULL_CHECK;
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenSetForeachKeyVarDefinition(
+    const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type)) {
+    code = ReplaceAll(CB_SET_FOREACH_VARS_DEF_KEY_PTR_TYPE)
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  } else {
+    code = ReplaceAll(CB_SET_FOREACH_VARS_DEF_KEY_BASE_TYPE)
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenSetErase(const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type))
+    code = CB_SET_ERASE_KEY_PTR_TYPE;
+  else
+    code = CB_SET_ERASE_KEY_BASE_TYPE;
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenSetInsert(const BaseType& type) {
+  std::string code;
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_SET_INSERT_KEY_USER_DEFINED_IMPL)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", type.GetFullName(true));
+  } else if (type.ToString() == "bundle") {
+    code = CB_SET_INSERT_KEY_BUNDLE_IMPL;
+  } else if (type.ToString() == "string" || type.ToString() == "file") {
+    code = CB_SET_INSERT_KEY_STRING_IMPL;
+  } else {
+    code = ReplaceAll(CB_SET_INSERT_KEY_BASE_IMPL)
+        .Change("<KEY_TYPE>",
+            RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenSetKeyNullCheck(const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type))
+    code = CB_SET_HANDLE_KEY_NULL_CHECK;
+  else
+    code = CB_SET_HANDLE_NULL_CHECK;
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenSetKeyFreeFunc(const BaseType& type) {
+  std::string code;
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
+    code = ReplaceAll(CB_SET_USER_DEFINED_FREE_FUNC)
+        .Change("<PREFIX>", GetHandlePrefix())
+        .Change("<NAME>", type.GetFullName(true));
+  } else if (type.ToString() == "bundle") {
+    code = CB_SET_BUNDLE_FREE_FUNC;
+  } else {
+    code = CB_SET_FREE_FUNC;
+  }
+
+  return code;
+}
+
+std::string CBodyGeneratorBase::GenSetCompareKeyVarsDefinition(
+    const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type)) {
+    code = ReplaceAll(CB_SET_COMPARE_KEY_VARS_DEF_PTR_TYPE)
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  } else {
+    code = ReplaceAll(CB_SET_COMPARE_KEY_VARS_DEF_BASE_TYPE)
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenSetUnitMapKeyRead(const BaseType& type) {
+  std::string code;
+  code = ReplaceAll(CB_SET_UNIT_MAP_KEY_READ)
+      .Change("<KEY>", type.GetFullName(true));
+  return RemoveLine(code);
+}
+
+std::string CBodyGeneratorBase::GenSetUnitMapKeyWrite(const BaseType& type) {
+  std::string code;
+  if (IsPtrType(type)) {
+    code = ReplaceAll(CB_SET_UNIT_MAP_KEY_WRITE_PTR_TYPE)
+        .Change("<KEY>", type.GetFullName(true))
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  } else {
+    code = ReplaceAll(CB_SET_UNIT_MAP_KEY_WRITE_BASE_TYPE)
+        .Change("<KEY>", type.GetFullName(true))
+        .Change("<KEY_TYPE>", RemoveLastSpaces(GetDataTypeString(type, false)));
+  }
+
+  return RemoveLine(code);
 }
 
 void CBodyGeneratorBase::GenStructureSetBase(std::ofstream& stream,
     const Structure& st) {
+  auto& key_elm = *(st.GetElements().begin());
+  auto& key_type = key_elm->GetType();
+  auto key_param_type = GetParamTypeString(ParameterType::Direction::IN,
+      key_type);
+
+  ReplaceAll(CB_STRUCTURE_SET_BASE)
+      .Change("<PREFIX>", GetHandlePrefix())
+      .Change("<NAME>", st.GetID())
+      .Change("<KEY_TYPE>", GetDataTypeString(key_type, false))
+      .Change("<KEY_PARAM_TYPE>", key_param_type)
+      .Change("<SET_UNIT_MAP_KEY_WRITE>", GenSetUnitMapKeyWrite(key_type))
+      .Change("<SET_UNIT_MAP_KEY_READ>", GenSetUnitMapKeyRead(key_type))
+      .Change("<SET_COMPARE_KEY_VARS_DEF>",
+          GenSetCompareKeyVarsDefinition(key_type))
+      .Change("<SET_KEY_FREE_FUNC>", GenSetKeyFreeFunc(key_type))
+      .Change("<SET_INSERT_ARGS_NULL_CHECK>", GenSetKeyNullCheck(key_type))
+      .Change("<SET_INSERT>", GenSetInsert(key_type))
+      .Change("<SET_ERASE_ARGS_NULL_CHECK>", GenSetKeyNullCheck(key_type))
+      .Change("<SET_ERASE>", GenSetErase(key_type))
+      .Change("<SET_FOREACH_VARS_DEF>",
+          GenSetForeachKeyVarDefinition(key_type))
+      .Change("<SET_CONTAINS_ARGS_NULL_CHECK>",
+          GenSetKeyExistNullCheck(key_type))
+      .Change("<SET_CONTAINS>", GenSetContains(key_type))
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
 }
 
 std::string CBodyGeneratorBase::GenBaseElementFree(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_FREE)
         .Change("<PREFIX>", GetHandlePrefix())
         .Change("<NAME>", GetFullNameFromType(type))
@@ -393,7 +926,9 @@ std::string CBodyGeneratorBase::GenBaseSet(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_SET)
         .Change("<PREFIX>", GetHandlePrefix())
         .Change("<NAME>", GetFullNameFromType(type))
@@ -419,7 +954,9 @@ std::string CBodyGeneratorBase::GenBaseGet(
     const std::unique_ptr<Element>& elm) {
   std::string code;
   auto& type = elm->GetType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_GET)
         .Change("<PREFIX>", GetHandlePrefix())
         .Change("<NAME>", GetFullNameFromType(type))
@@ -479,14 +1016,56 @@ void CBodyGeneratorBase::GenStructureBase(std::ofstream& stream,
 void CBodyGeneratorBase::AddParameterType(const Interface& iface,
     const BaseType& type, ParameterType::Direction direction) {
   if (IsDelegateType(iface, type)) {
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType("delegate", "delegate", true),
+          ParameterType::Direction::IN));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType("delegate", "delegate", true),
+          ParameterType::Direction::OUT));
     return;
-  } else if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  } else if (type.IsUserDefinedType()) {
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(type), ParameterType::Direction::IN));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(type), ParameterType::Direction::OUT));
+  } else if (type.GetMetaType() != nullptr) {
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(type), ParameterType::Direction::IN));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(type), ParameterType::Direction::OUT));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(*type.GetMetaType()), ParameterType::Direction::IN));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(*type.GetMetaType()), ParameterType::Direction::OUT));
+  } else if (type.GetKeyType() != nullptr) {
     AddParameterType(
         std::make_shared<ParameterType>(
           new BaseType(type), ParameterType::Direction::IN));
     AddParameterType(
         std::make_shared<ParameterType>(
           new BaseType(type), ParameterType::Direction::OUT));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(*type.GetKeyType()), ParameterType::Direction::IN));
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(*type.GetKeyType()), ParameterType::Direction::OUT));
+    if (type.GetValueType() != nullptr) {
+      AddParameterType(
+          std::make_shared<ParameterType>(
+            new BaseType(*type.GetValueType()), ParameterType::Direction::IN));
+      AddParameterType(
+          std::make_shared<ParameterType>(
+            new BaseType(*type.GetValueType()), ParameterType::Direction::OUT));
+    }
   } else if (type.GetFullName() != "file") {
     AddParameterType(
         std::make_shared<ParameterType>(
@@ -496,7 +1075,7 @@ void CBodyGeneratorBase::AddParameterType(const Interface& iface,
 
 void CBodyGeneratorBase::AddParameterType(
     std::shared_ptr<ParameterType> param_type) {
-  std::string key = param_type->GetBaseType().GetFullName() +
+  std::string key = param_type->GetBaseType().GetFullName(true) +
       std::to_string(static_cast<int>(param_type->GetDirection()));
 
   if (param_types_.find(key) != param_types_.end())
@@ -547,11 +1126,7 @@ void CBodyGeneratorBase::GenParameterMap() {
           AddParameterType(
               std::make_shared<ParameterType>(
                 new BaseType("delegate", "delegate", true),
-                  ParameterType::Direction::IN));
-          AddParameterType(
-              std::make_shared<ParameterType>(
-                new BaseType("delegate", "delegate", true),
-                  ParameterType::Direction::OUT));
+                ParameterType::Direction::OUT));
           AddParameterType(
               std::make_shared<ParameterType>(
                 new BaseType(iface.GetID() + "_" + decl->GetID(), "", true),
@@ -584,6 +1159,23 @@ void CBodyGeneratorBase::GenParameterMap() {
       }
     }
   }
+
+  for (auto& i : GetStructures()) {
+    auto& st = *i.second;
+    AddParameterType(
+        std::make_shared<ParameterType>(
+          new BaseType(st.GetID(), st.GetID(), true)));
+
+    for (auto& elm : st.GetElements()) {
+      auto& type = elm->GetType();
+      AddParameterType(
+          std::make_shared<ParameterType>(
+            new BaseType(type), ParameterType::Direction::IN));
+      AddParameterType(
+          std::make_shared<ParameterType>(
+            new BaseType(type), ParameterType::Direction::OUT));
+    }
+  }
 }
 
 void CBodyGeneratorBase::GenUnitMapBase(std::ofstream& stream) {
@@ -624,7 +1216,9 @@ std::string CBodyGeneratorBase::GenUnitMapWrite(
     const ParameterType& param_type) {
   std::string code;
   auto& type = param_type.GetBaseType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     if (type.ToString() == "delegate") {
       code = std::string(CB_UNIT_MAP_DELEGATE_WRITE);
     } else {
@@ -654,7 +1248,9 @@ std::string CBodyGeneratorBase::GenUnitMapRead(
     const ParameterType& param_type) {
   std::string code;
   auto& type = param_type.GetBaseType();
-  if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) {
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr ||
+      type.GetKeyType() != nullptr) {
     if (type.ToString() == "delegate") {
       code = std::string(CB_UNIT_MAP_DELEGATE_READ);
     } else {
index 34f6cad..aae3b42 100644 (file)
@@ -59,7 +59,41 @@ class CBodyGeneratorBase : public tidl::CBodyGeneratorBase {
   std::string GenListAdd(const std::unique_ptr<Element>& elm);
   std::string GenListCallbackParamType(const std::unique_ptr<Element>& elm);
   void GenStructureListBase(std::ofstream& stream, const Structure& st);
+  std::string GenMapContains(const BaseType& key_type);
+  std::string GenMapKeyExistNullCheck(const BaseType& key_type);
+  std::string GenMapForeachVarsDefinition(const BaseType& key_type,
+      const BaseType& value_type);
+  std::string GenMapErase(const BaseType& key_type);
+  std::string GenMapKeyNullCheck(const BaseType& key_type);
+  std::string GenMapLookupValueSet(const BaseType& value_type);
+  std::string GenMapLookup(const BaseType& key_type,
+      const BaseType& value_type);
+  std::string GenMapKeyValueNullCheck(const BaseType& key_type);
+  std::string GenMapInsertNewKeyFree(const BaseType& key_type);
+  std::string GenMapInsertNewValueImpl(const BaseType& key_type,
+      const BaseType& value_type);
+  std::string GenMapInsertNewKeyImpl(const BaseType& key_type);
+  std::string GenMapInsert(const BaseType& key_type,
+      const BaseType& value_type);
+  std::string GenMapKeyValueNullCheck(const BaseType& key_type,
+      const BaseType& value_type);
+  std::string GenMapFreeFunc(const BaseType& type);
+  std::string GenMapCompareKeyVarsDefinition(const BaseType& type);
+  std::string GenMapUnitMapValueRead(const BaseType& type);
+  std::string GenMapUnitMapKeyRead(const BaseType& type);
+  std::string GenMapUnitMapValueWrite(const BaseType& type);
+  std::string GenMapUnitMapKeyWrite(const BaseType& type);
   void GenStructureMapBase(std::ofstream& stream, const Structure& st);
+  std::string GenSetContains(const BaseType& type);
+  std::string GenSetKeyExistNullCheck(const BaseType& type);
+  std::string GenSetForeachKeyVarDefinition(const BaseType& type);
+  std::string GenSetErase(const BaseType& type);
+  std::string GenSetInsert(const BaseType& type);
+  std::string GenSetKeyNullCheck(const BaseType& type);
+  std::string GenSetKeyFreeFunc(const BaseType& type);
+  std::string GenSetCompareKeyVarsDefinition(const BaseType& type);
+  std::string GenSetUnitMapKeyRead(const BaseType& type);
+  std::string GenSetUnitMapKeyWrite(const BaseType& type);
   void GenStructureSetBase(std::ofstream& stream, const Structure& st);
   std::string GenBaseElementFree(const std::unique_ptr<Element>& elm);
   std::string GenBaseElementsFree(const Elements& elms);
diff --git a/idlc/gen/version2/c_body_generator_map_base_cb.hh b/idlc/gen/version2/c_body_generator_map_base_cb.hh
new file mode 100644 (file)
index 0000000..93f7680
--- /dev/null
@@ -0,0 +1,789 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDLC_GEN_VERSION2_C_BODY_GENERATOR_MAP_BASE_CB_HH_
+#define IDLC_GEN_VERSION2_C_BODY_GENERATOR_MAP_BASE_CB_HH_
+
+namespace tidl {
+namespace version2 {
+
+/**
+ * <PREFIX> The prefix of the map structure.
+ * <NAME> The name of the map structure.
+ */
+constexpr const char CB_STRUCTURE_MAP_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  GTree *node;
+  <PREFIX>_<NAME>_compare_cb compare_cb;
+  void *user_data;
+} <PREFIX>_<NAME>_t;
+
+static <PREFIX>_<NAME>_compare_cb __<PREFIX>_<NAME>_compare_cb;
+static void *__<PREFIX>_<NAME>_user_data;
+
+typedef struct <PREFIX>_<NAME>_traverse_info_s {
+  rpc_port_unit_map_h map;
+  int number;
+} <PREFIX>_<NAME>_traverse_info_t;
+
+typedef struct <PREFIX>_<NAME>_foreach_info_s {
+  <PREFIX>_<NAME>_foreach_cb callback;
+  void *user_data;
+} <PREFIX>_<NAME>_foreach_info_t;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the map structure.
+ * <NAME> The name of the map structure.
+ * <KEY_TYPE> The type of the key of the map.
+ * <VALUE_TYPE> The type of the value of the map.
+ * <KEY_PARAM_TYPE> The parameter type of the key of the map.
+ * <VALUE_PARAM_TYPE> The parameter type of the value of the map.
+ * <VALUE_PARAM_TYPE_OUT> The output parameter type of the value of the map.
+ * <MAP_UNIT_MAP_KEY_WRITE> The implementation to write the key  to the unit map.
+ * <MAP_UNIT_MAP_VALUE_WRITE> The implementation to write the value to the unit map.
+ * <MAP_UNIT_MAP_KEY_READ> The implementation to read the key from the unit map.
+ * <MAP_UNIT_MAP_VALUE_READ> The implementation to read the value from the unit map.
+ * <MAP_COMPARE_KEY_VARS_DEF> The definition of the key variables of the compare callback function.
+ * <MAP_KEY_FREE_FUNC> The implementation to free the key.
+ * <MAP_VALUE_FREE_FUNC> The implementation to free the value.
+ * <MAP_INSERT_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <MAP_INSERT> The implementation to insert the key and the value to the map.
+ * <MAP_LOOKUP_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <MAP_LOOKUP> The implementation to set the lookuped data to the output value.
+ * <MAP_ERASE_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <MAP_ERASE> The implementation to erase the element from the map.
+ * <MAP_REPLACE_ARGS_NULL_CHECK> The impementation to check whether the arg is nullptr or not.
+ * <MAP_FOREACH_KEY_VAR_DEF> The definition of the key variable of the foreach callback function.
+ * <MAP_FOREACH_VALUE_VAR_DEF> The definition of the value variable of the foreach callback function.
+ * <MAP_CONTAINS_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <MAP_CONTAINS> The implementation to check whether the key exists or not.
+ */
+constexpr const char CB_STRUCTURE_MAP_BASE[] =
+R"__c_cb(
+static gboolean __<PREFIX>_<NAME>_traverse_cb(gpointer key, gpointer value, gpointer user_data)
+{
+  <PREFIX>_<NAME>_traverse_info_t *info = user_data;
+  char name[32];
+
+  snprintf(name, sizeof(name), "key-%d", info->number);
+  <MAP_UNIT_MAP_KEY_WRITE>
+
+  snprintf(name, sizeof(name), "value-%d", info->number++);
+  <MAP_UNIT_MAP_VALUE_WRITE>
+
+  return TRUE;
+}
+
+static void __<PREFIX>_<NAME>_to(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_traverse_info_t info;
+  <PREFIX>_<NAME>_h h = data;
+  rpc_port_unit_map_h map;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  map = rpc_port_unit_map_create();
+  if (map == nullptr) {
+    _E("Failed to create unit map");
+    set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  rpc_port_unit_map_write_int(map, "size", g_tree_nnodes(h->node));
+
+  info.map = map;
+  info.number = 0;
+  g_tree_foreach(h->node, __<PREFIX>_<NAME>_traverse_cb, &info);
+
+  rpc_port_parcel_write(parcel, &map->parcelable, map);
+  rpc_port_unit_map_destroy(map);
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static void __<PREFIX>_<NAME>_from(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  <KEY_TYPE>key;
+  <VALUE_TYPE>value;
+  rpc_port_unit_map_h map;
+  char name[32];
+  int size = 0;
+  int ret;
+  int i;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  map = rpc_port_unit_map_create();
+  if (map == nullptr) {
+    _E("Failed to create unit map");
+    set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  rpc_port_parcel_read(parcel, &map->parcelable, map);
+
+  ret = rpc_port_unit_map_read_int(parcel, "size", &size);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read size. error(%d)", ret);
+    rpc_port_unit_map_destroy(map);
+    set_last_result(ret);
+    return;
+  }
+
+  for (i = 0; i < size; ++i) {
+    snprintf(name, sizeof(name), "key-%d", i);
+    <MAP_UNIT_MAP_KEY_READ>
+    snprintf(name, sizeof(name), "value-%d", i);
+    <MAP_UNIT_MAP_VALUE_READ>
+
+    ret = <PREFIX>_<NAME>_insert(h, key, value);
+    if (ret != RPC_PORT_ERROR_NONE) {
+      rpc_port_unit_map_destroy(map);
+      set_last_result(ret);
+      return;
+    }
+  }
+
+  rpc_port_unit_map_destroy(map);
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static gint __<PREFIX>_<NAME>_comparison_cb(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+  <MAP_COMPARE_KEY_VARS_DEF>
+
+  if (__<PREFIX>_<NAME>_compare_cb == nullptr) {
+    _E("<PREFIX>_<NAME>_set_compare_cb() MUST be called");
+    return -1;
+  }
+
+  return __<PREFIX>_<NAME>_compare_cb(key_a, key_b, __<PREFIX>_<NAME>_user_data);
+}
+
+int <PREFIX>_<NAME>_create(<PREFIX>_<NAME>_h *h)
+{
+  <PREFIX>_<NAME>_t *handle;
+
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  if (__<PREFIX>_<NAME>_compare_cb == nullptr) {
+    _E("<PREFIX>_<NAME>_set_compare_cb() MUST be called");
+    return RPC_PORT_ERROR_IO_ERROR;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->node = g_tree_new_full((GCompareDataFunc)__<PREFIX>_<NAME>_comparison_cb, handle, (GDestroyNotify)<MAP_KEY_FREE_FUNC>, (GDestroyNotify)<MAP_VALUE_FREE_FUNC>);
+  if (handle->node == nullptr) {
+    _E("g_tree_new_full() is failed");
+    free(handle);
+    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;
+  }
+
+  if (h->node)
+    g_tree_destroy(h->node);
+
+  free(h);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone)
+{
+  rpc_port_unit_map_h map;
+  int ret;
+
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  map = rpc_port_unit_map_create();
+  if (map == nullptr) {
+    _E("Failed to create unit map");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  ret = rpc_port_unit_map_write_<NAME>(map, "clone", h);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to write <NAME>. error(%d)", ret);
+    rpc_port_unit_map_destroy(map);
+    return ret;
+  }
+
+  ret = rpc_port_unit_map_read_<NAME>(map, "clone", clone);
+  rpc_port_unit_map_destroy(map);
+
+  return ret;
+}
+
+int <PREFIX>_<NAME>_set_compare_cb(<PREFIX>_<NAME>_compare_cb callback, void *user_data)
+{
+  if (callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  __<PREFIX>_<NAME>_compare_cb = callback;
+  __<PREFIX>_<NAME>_user_data = user_data;
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_insert(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE>value)
+{
+  int ret;
+
+  if (<MAP_INSERT_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <MAP_INSERT>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_lookup(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE_OUT>value)
+{
+  gpointer data;
+
+  if (<MAP_LOOKUP_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <MAP_LOOKUP>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_erase(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key)
+{
+  if (<MAP_ERASE_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <MAP_ERASE>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_replace(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE>value)
+{
+  if (<MAP_REPLACE_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <PREFIX>_<NAME>_erase(h, key);
+  return <PREFIX>_<NAME>_insert(h, key, value);
+}
+
+static gboolean __<PREFIX>_<NAME>_foreach_cb(gpointer key, gpointer value, gpointer user_data)
+{
+  <PREFIX>_<NAME>_foreach_info_t *info = user_data;
+  <MAP_FOREACH_VARS_DEF>
+
+  return info->callback(tmp_key, tmp_value, info->user_data);
+}
+
+int <PREFIX>_<NAME>_foreach(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_foreach_cb callback, void *user_data)
+{
+  <PREFIX>_<NAME>_foreach_info_t info;
+
+  if (h == nullptr || callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  info.callback = callback;
+  info.user_data = user_data;
+
+  g_tree_foreach(h->node, __<PREFIX>_<NAME>_foreach_cb, &info);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_contains(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, bool *exist)
+{
+  gpointer data;
+
+  if (<MAP_CONTAINS_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <MAP_CONTAINS>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_size(<PREFIX>_<NAME>_h h, size_t *size)
+{
+  if (h == nullptr || size == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  *size = g_tree_nnodes(h->node);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_clear(<PREFIX>_<NAME>_h h)
+{
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  g_tree_remove_all(h->node);
+
+  return RPC_PORT_ERROR_NONE;
+}
+)__c_cb";
+
+/**
+ * <KEY> The name of the key.
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_MAP_UNIT_MAP_KEY_WRITE_PTR_TYPE[] =
+R"__c_cb(
+rpc_port_unit_map_write_<KEY>(info->map, name, (<KEY_TYPE>)key);
+)__c_cb";
+
+/**
+ * <KEY> The name of the key.
+ * <KEY_TYPE> The pointer type of the key.
+ */
+constexpr const char CB_MAP_UNIT_MAP_KEY_WRITE_BASE_TYPE[] =
+R"__c_cb(
+rpc_port_unit_map_write_<KEY>(info->map, name, *(<KEY_TYPE> *)key);
+)__c_cb";
+
+/**
+ * <VALUE> The name of the value.
+ * <VALUE_TYPE> The type of the value.
+ */
+constexpr const char CB_MAP_UNIT_MAP_VALUE_WRITE_PTR_TYPE[] =
+R"__c_cb(
+rpc_port_unit_map_write_<VALUE>(info->map, name, (<VALUE_TYPE>)value);
+)__c_cb";
+
+/**
+ * <VALUE> The name of the value.
+ * <VALUE_TYPE> The pointer type of the value.
+ */
+constexpr const char CB_MAP_UNIT_MAP_VALUE_WRITE_BASE_TYPE[] =
+R"__c_cb(
+rpc_port_unit_map_write_<VALUE>(info->map, name, *(<VALUE_TYPE> *)value);
+)__c_cb";
+
+/**
+ * <KEY> The name of the key.
+ */
+constexpr const char CB_MAP_UNIT_MAP_KEY_READ[] =
+R"__c_cb(
+rpc_port_unit_map_read_<KEY>(map, name, &key);
+)__c_cb";
+
+/**
+ * <VALUE> The name of the value.
+ */
+constexpr const char CB_MAP_UNIT_MAP_VALUE_READ[] =
+R"__c_cb(
+rpc_port_unit_map_read_<VALUE>(map, name, &value);
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_MAP_COMPARE_KEY_VARS_DEF_PTR_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> key_a = (<KEY_TYPE>)a;
+<KEY_TYPE> key_b = (<KEY_TYPE>)b;
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_MAP_COMPARE_KEY_VARS_DEF_BASE_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> key_a = *(<KEY_TYPE> *)a;
+<KEY_TYPE> key_b = *(<KEY_TYPE> *)b;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ */
+constexpr const char CB_MAP_USER_DEFINED_FREE_FUNC[] =
+R"__c_cb(<PREFIX>_<NAME>_destroy)__c_cb";
+
+constexpr const char CB_MAP_BUNDLE_FREE_FUNC[] =
+R"__c_cb(bundle_free)__c_cb";
+
+constexpr const char CB_MAP_FREE_FUNC[] =
+R"__c_cb(free)__c_cb";
+
+constexpr const char CB_MAP_HANDLE_KEY_VALUE_NULL_CHECK[] =
+R"__c_cb(h == nullptr || key == nullptr || value == nullptr)__c_cb";
+
+constexpr const char CB_MAP_HANDLE_KEY_NULL_CHECK[] =
+R"__c_cb(h == nullptr || key == nullptr)__c_cb";
+
+constexpr const char CB_MAP_HANDLE_VALUE_NULL_CHECK[] =
+R"__c_cb(h == nullptr || value == nullptr)__c_cb";
+
+constexpr const char CB_MAP_HANDLE_KEY_EXIST_NULL_CHECK[] =
+R"__c_cb(h == nullptr || key == nullptr || exist == nullptr)__c_cb";
+
+constexpr const char CB_MAP_HANDLE_EXIST_NULL_CHECK[] =
+R"__c_cb(h == nullptr || exist == nullptr)__c_cb";
+
+constexpr const char CB_MAP_HANDLE_NULL_CHECK[] =
+R"__c_cb(h == nullptr)__c_cb";
+
+/**
+ * <MAP_INSERT_NEW_KEY_IMPL> The implementation to create a new varaible of the key for the map container.
+ * <MAP_INSERT_NEW_VALUE_IMPL> The implementation to create a new varaible of the value for the map container.
+ */
+constexpr const char CB_MAP_INSERT[] =
+R"__c_cb(
+<MAP_INSERT_NEW_KEY_IMPL>
+<MAP_INSERT_NEW_VALUE_IMPL>
+
+g_tree_insert(h->node, (gpointer)new_key, (gpointer)new_value);
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ */
+constexpr const char CB_MAP_INSERT_NEW_KEY_USER_DEFINED_IMPL[] =
+R"__c_cb(
+if (g_tree_lookup(h->node, (gpointer)key) != nullptr) {
+  _E("Already exists. Try to use replace function");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+<PREFIX>_<NAME>_h new_key = nullptr;
+ret = <PREFIX>_<NAME>_clone(key, &new_key);
+if (ret != RPC_PORT_ERROR_NONE)
+  return ret;
+)__c_cb";
+
+constexpr const char CB_MAP_INSERT_NEW_KEY_BUNDLE_IMPL[] =
+R"__c_cb(
+if (g_tree_lookup(h->node, (gpointer)key) != nullptr) {
+  _E("Already exists. Try to use replace function");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+bundle *new_key = bundle_dup(key);
+if (new_key == nullptr) {
+  ret = RPC_PORT_ERROR_INVALID_PARAMETER;
+  return ret;
+}
+)__c_cb";
+
+constexpr const char CB_MAP_INSERT_NEW_KEY_STRING_IMPL[] =
+R"__c_cb(
+if (g_tree_lookup(h->node, (gpointer)key) != nullptr) {
+  _E("Already exists. Try to use replace function");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+char *new_key = strdup(key);
+if (new_key == nullptr) {
+  ret = RPC_PORT_ERROR_INVALID_PARAMETER;
+  return ret;
+}
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_MAP_INSERT_NEW_KEY_BASE_IMPL[] =
+R"__c_cb(
+<KEY_TYPE> *new_key = malloc(sizeof(<KEY_TYPE>));
+if (new_key == nullptr) {
+  _E("malloc() is failed");
+  ret = RPC_PORT_ERROR_OUT_OF_MEMORY;
+  return ret;
+}
+
+*new_key = key;
+if (g_tree_lookup(h->node, (gpointer)new_key) != nullptr) {
+  _E("Already exists. Try to use replace function");
+  free(new_key);
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ * <MAP_INSERT_NEW_KEY_FREE> The implementation to free the newly key variable.
+ */
+constexpr const char CB_MAP_INSERT_NEW_VALUE_USER_DEFINED_IMPL[] =
+R"__c_cb(
+<PREFIX>_<NAME>_h new_value = nullptr;
+ret = <PREFIX>_<NAME>_clone(value, &new_value);
+if (ret != RPC_PORT_ERROR_NONE) {
+  <MAP_INSERT_NEW_KEY_FREE>
+  return ret;
+}
+)__c_cb";
+
+/**
+ * <MAP_INSERT_NEW_KEY_FREE> The implementation to free the newly key variable.
+ */
+constexpr const char CB_MAP_INSERT_NEW_VALUE_BUNDLE_IMPL[] =
+R"__c_cb(
+bundle *new_value = bundle_dup(value);
+if (new_value == nullptr) {
+  <MAP_INSERT_NEW_KEY_FREE>
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+)__c_cb";
+
+/**
+ * <MAP_INSERT_NEW_KEY_FREE> The implementation to free the newly key variable.
+ */
+constexpr const char CB_MAP_INSERT_NEW_VALUE_STRING_IMPL[] =
+R"__c_cb(
+char *new_value = strdup(value);
+if (new_value == nullptr) {
+  <MAP_INSERT_NEW_KEY_FREE>
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+)__c_cb";
+
+/**
+ * <VALUE_TYPE> The type of the value.
+ * <MAP_INSERT_NEW_KEY_FREE> The implementation to free the newly key variable.
+ */
+constexpr const char CB_MAP_INSERT_NEW_VALUE_BASE_IMPL[] =
+R"__c_cb(
+<VALUE_TYPE> *new_value = malloc(sizeof(<VALUE_TYPE>));
+if (new_value == nullptr) {
+  <MAP_INSERT_NEW_KEY_FREE>
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+*new_value = value;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ */
+constexpr const char CB_MAP_INSERT_NEW_KEY_USER_DEFINED_FREE[] =
+R"__c_cb(
+<PREFIX>_<NAME>_destroy(new_key);
+)__c_cb";
+
+constexpr const char CB_MAP_INSERT_NEW_KEY_BUNDLE_FREE[] =
+R"__c_cb(
+bundle_free(new_key);
+)__c_cb";
+
+constexpr const char CB_MAP_INSERT_NEW_KEY_STRING_FREE[] =
+R"__c_cb(
+free(new_key);
+)__c_cb";
+
+constexpr const char CB_MAP_INSERT_NEW_KEY_BASE_FREE[] =
+R"__c_cb(
+free(new_key);
+)__c_cb";
+
+/**
+ * <MAP_LOOKUP_VALUE_SET> The implementation to set the value for the map container.
+ */
+constexpr const char CB_MAP_LOOKUP_KEY_PTR_TYPE[] =
+R"__c_cb(
+data = g_tree_lookup(h->node, (gpointer)key);
+if (data == nullptr) {
+  _E("g_tree_lookup() is failed");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+<MAP_LOOKUP_VALUE_SET>
+)__c_cb";
+
+/**
+ * <MAP_LOOKUP_VALUE_SET> The implementation to set the value for the map container.
+ */
+constexpr const char CB_MAP_LOOKUP_KEY_BASE_TYPE[] =
+R"__c_cb(
+data = g_tree_lookup(h->node, (gpointer)&key);
+if (data == nullptr) {
+  _E("g_tree_lookup() is failed");
+  return RPC_PORT_ERROR_INVALID_PARAMETER;
+}
+
+<MAP_LOOKUP_VALUE_SET>
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ */
+constexpr const char CB_MAP_LOOKUP_VALUE_USER_DEFINED_SET[] =
+R"__c_cb(
+<PREFIX>_<NAME>_h new_value = nullptr;
+int ret = <PREFIX>_<NAME>_clone((<PREFIX>_<NAME>_h)data, &new_value);
+if (ret != RPC_PORT_ERROR_NONE)
+  return ret;
+
+*value = (<PREFIX>_<NAME>_h)new_value;
+)__c_cb";
+
+constexpr const char CB_MAP_LOOKUP_VALUE_BUNDLE_SET[] =
+R"__c_cb(
+bundle *new_value = bundle_dup((bundle *)data);
+if (new_value == nullptr) {
+  _E("bundle_dup() is failed");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+*value = new_value;
+)__c_cb";
+
+constexpr const char CB_MAP_LOOKUP_VALUE_STRING_SET[] =
+R"__c_cb(
+char *new_value = strdup((char *)data);
+if (new_value == nullptr) {
+  _E("strdup() is failed'0;
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+*value = new_value;
+)__c_cb";
+
+/**
+ * <VALUE_TYPE> The type of the value.
+ */
+constexpr const char CB_MAP_LOOKUP_VALUE_BASE_SET[] =
+R"__c_cb(
+*value = *(<VALUE_TYPE> *)data;
+)__c_cb";
+
+constexpr const char CB_MAP_ERASE_KEY_PTR_TYPE[] =
+R"__c_cb(
+if (!g_tree_remove(h->node, (gpointer)key))
+  _W("g_tree_remove() is failed");
+)__c_cb";
+
+constexpr const char CB_MAP_ERASE_KEY_BASE_TYPE[] =
+R"__c_cb(
+if (!g_tree_remove(h->node, (gpointer)&key))
+  _W("g_tree_remove() is failed");
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ * <VALUE_TYPE> the type of the value.
+ */
+constexpr const char CB_MAP_FOREACH_VARS_DEF_KEY_PTR_VALUE_PTR_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> tmp_key = (<KEY_TYPE>)key;
+<VALUE_TYPE> tmp_value = (<VALUE_TYPE>)value;
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ * <VALUE_TYPE> the type of the value.
+ */
+constexpr const char CB_MAP_FOREACH_VARS_DEF_KEY_PTR_VALUE_BASE_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> tmp_key = (<KEY_TYPE>)key;
+<VALUE_TYPE> tmp_value = *(<VALUE_TYPE> *)value;
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ * <VALUE_TYPE> the type of the value.
+ */
+constexpr const char CB_MAP_FOREACH_VARS_DEF_KEY_BASE_VALUE_PTR_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> tmp_key = *(<KEY_TYPE> *)key;
+<VALUE_TYPE> tmp_value = (<VALUE_TYPE>)value;
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ * <VALUE_TYPE> the type of the value.
+ */
+constexpr const char CB_MAP_FOREACH_VARS_DEF_KEY_BASE_VALUE_BASE_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> tmp_key = *(<KEY_TYPE> *)key;
+<VALUE_TYPE> tmp_value = *(<VALUE_TYPE> *)value;
+)__c_cb";
+
+constexpr const char CB_MAP_CONTAINS_KEY_PTR_TYPE[] =
+R"__c_cb(
+data = g_tree_lookup(h->node, (gpointer)key);
+*exist = (data != nullptr) ? true : false;
+)__c_cb";
+
+constexpr const char CB_MAP_CONTAINS_KEY_BASE_TYPE[] =
+R"__c_cb(
+data = g_tree_lookup(h->node, (gpointer)&key);
+*exist = (data != nullptr) ? true : false;
+)__c_cb";
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_C_BODY_GENERATOR_MAP_BASE_CB_HH_
diff --git a/idlc/gen/version2/c_body_generator_set_base_cb.hh b/idlc/gen/version2/c_body_generator_set_base_cb.hh
new file mode 100644 (file)
index 0000000..2ea2554
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDLC_GEN_VERSION2_C_BODY_GENERATOR_SET_BASE_CB_HH_
+#define IDLC_GEN_VERSION2_C_BODY_GENERATOR_SET_BASE_CB_HH_
+
+namespace tidl {
+namespace version2 {
+
+/**
+ * <PREFIX> The prefix of the set structure.
+ * <NAME> The name of the set structure.
+ */
+constexpr const char CB_STRUCTURE_SET_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_s {
+  rpc_port_parcelable_t parcelable;
+  GTree *node;
+} <PREFIX>_<NAME>_t;
+
+static <PREFIX>_<NAME>_compare_cb __<PREFIX>_<NAME>_compare_cb;
+static void *__<PREFIX>_<NAME>_user_data;
+
+typedef struct <PREFIX>_<NAME>_traverse_info_s {
+  rpc_port_unit_map_h map;
+  int number;
+} <PREFIX>_<NAME>_traverse_info_t;
+
+typedef struct <PREFIX>_<NAME>_foreach_info_s {
+  <PREFIX>_<NAME>_foreach_cb callback;
+  void *user_data;
+} <PREFIX>_<NAME>_foreach_info_t;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the set structure.
+ * <NAME> The name of the set structure.
+ * <KEY_TYPE> The type of the key of the set.
+ * <KEY_PARAM_TYPE> The parameter type of the key of the set.
+ * <SET_UNIT_MAP_KEY_WRITE> The implementation to write the key  to the unit map.
+ * <SET_UNIT_MAP_KEY_READ> The implementation to read the key from the unit map.
+ * <SET_COMPARE_KEY_VARS_DEF> The definition of the key variables of the compare callback function.
+ * <SET_KEY_FREE_FUNC> The implementation to free the key.
+ * <SET_INSERT_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <SET_INSERT> The implementation to insert the key and the value to the set.
+ * <SET_ERASE_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <SET_ERASE> The implementation to erase the element from the set.
+ * <SET_FOREACH_KEY_VAR_DEF> The definition of the key variable of the foreach callback function.
+ * <SET_CONTAINS_ARGS_NULL_CHECK> The implementation to check whether the arg is nullptr or not.
+ * <SET_CONTAINS> The implementation to check whether the key exists or not.
+ */
+constexpr const char CB_STRUCTURE_SET_BASE[] =
+R"__c_cb(
+static gboolean __<PREFIX>_<NAME>_traverse_cb(gpointer key, gpointer value, gpointer user_data)
+{
+  <PREFIX>_<NAME>_traverse_info_t *info = user_data;
+  char name[32];
+
+  snprintf(name, sizeof(name), "key-%d", info->number++);
+  <SET_UNIT_MAP_KEY_WRITE>
+
+  return TRUE;
+}
+
+static void __<PREFIX>_<NAME>_to(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_traverse_info_t info;
+  <PREFIX>_<NAME>_h h = data;
+  rpc_port_unit_map_h map;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  map = rpc_port_unit_map_create();
+  if (map == nullptr) {
+    _E("Failed to create unit map");
+    set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  rpc_port_unit_map_write_int(map, "size", g_tree_nnodes(h->node));
+
+  info.map = map;
+  info.number = 0;
+  g_tree_foreach(h->node, __<PREFIX>_<NAME>_traverse_cb, &info);
+
+  rpc_port_parcel_write(parcel, &map->parcelable, map);
+  rpc_port_unit_map_destroy(map);
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static void __<PREFIX>_<NAME>_from(rpc_port_parcel_h parcel, void *data)
+{
+  <PREFIX>_<NAME>_h h = data;
+  <KEY_TYPE>key;
+  rpc_port_unit_map_h map;
+  char name[32];
+  int size = 0;
+  int ret;
+  int i;
+
+  if (parcel == nullptr || h == nullptr) {
+    _E("Invalid parameter");
+    set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER);
+    return;
+  }
+
+  map = rpc_port_unit_map_create();
+  if (map == nullptr) {
+    _E("Failed to create unit map");
+    set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY);
+    return;
+  }
+
+  rpc_port_parcel_read(parcel, &map->parcelable, map);
+
+  ret = rpc_port_unit_map_read_int(parcel, "size", &size);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to read size. error(%d)", ret);
+    rpc_port_unit_map_destroy(map);
+    set_last_result(ret);
+    return;
+  }
+
+  for (i = 0; i < size; ++i) {
+    snprintf(name, sizeof(name), "key-%d", i);
+    <SET_UNIT_MAP_KEY_READ>
+
+    ret = <PREFIX>_<NAME>_insert(h, key);
+    if (ret != RPC_PORT_ERROR_NONE) {
+      rpc_port_unit_map_destroy(map);
+      set_last_result(ret);
+      return;
+    }
+  }
+
+  rpc_port_unit_map_destroy(map);
+  set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static gint __<PREFIX>_<NAME>_comparison_cb(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+  <SET_COMPARE_KEY_VARS_DEF>
+
+  if (__<PREFIX>_<NAME>_compare_cb == nullptr) {
+    _E("<PREFIX>_<NAME>_set_compare_cb() MUST be called");
+    return -1;
+  }
+
+  return __<PREFIX>_<NAME>_compare_cb(key_a, key_b, __<PREFIX>_<NAME>_user_data);
+}
+
+int <PREFIX>_<NAME>_set_compare_cb(<PREFIX>_<NAME>_compare_cb callback, void *user_data)
+{
+  if (callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  __<PREFIX>_<NAME>_compare_cb = callback;
+  __<PREFIX>_<NAME>_user_data = user_data;
+
+  return 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;
+  }
+
+  if (__<PREFIX>_<NAME>_compare_cb == nullptr) {
+    _E("<PREFIX>_<NAME>_set_compare_cb() MUST be called");
+    return RPC_PORT_ERROR_IO_ERROR;
+  }
+
+  handle = calloc(1, sizeof(<PREFIX>_<NAME>_t));
+  if (handle == nullptr) {
+    _E("Out of memory");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->node = g_tree_new_full((GCompareDataFunc)__<PREFIX>_<NAME>_comparison_cb, handle, (GDestroyNotify)<SET_KEY_FREE_FUNC>, nullptr);
+  if (handle->node == nullptr) {
+    _E("g_tree_new_full() is failed");
+    free(handle);
+    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;
+  }
+
+  if (h->node)
+    g_tree_destroy(h->node);
+
+  free(h);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_clone(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_h *clone)
+{
+  rpc_port_unit_map_h map;
+  int ret;
+
+  if (h == nullptr || clone == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  map = rpc_port_unit_map_create();
+  if (map == nullptr) {
+    _E("Failed to create unit map");
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
+  }
+
+  ret = rpc_port_unit_map_write_<NAME>(map, "clone", h);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to write <NAME>. error(%d)", ret);
+    rpc_port_unit_map_destroy(map);
+    return ret;
+  }
+
+  ret = rpc_port_unit_map_read_<NAME>(map, "clone", clone);
+  rpc_port_unit_map_destroy(map);
+
+  return ret;
+}
+
+int <PREFIX>_<NAME>_insert(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key)
+{
+  if (<SET_INSERT_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <SET_INSERT>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_erase(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key)
+{
+  if (<SET_ERASE_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <SET_ERASE>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+static gboolean __<PREFIX>_<NAME>_foreach_cb(gpointer key, gpointer value, gpointer user_data)
+{
+  <PREFIX>_<NAME>_foreach_info_t *info = user_data;
+  <SET_FOREACH_VARS_DEF>
+
+  return info->callback(tmp_key, info->user_data);
+}
+
+int <PREFIX>_<NAME>_foreach(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_foreach_cb callback, void *user_data)
+{
+  <PREFIX>_<NAME>_foreach_info_t info;
+
+  if (h == nullptr || callback == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  info.callback = callback;
+  info.user_data = user_data;
+
+  g_tree_foreach(h->node, __<PREFIX>_<NAME>_foreach_cb, &info);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_contains(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, bool *exist)
+{
+  gpointer data;
+
+  if (<SET_CONTAINS_ARGS_NULL_CHECK>) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  <SET_CONTAINS>
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_size(<PREFIX>_<NAME>_h h, size_t *size)
+{
+  if (h == nullptr || size == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  *size = g_tree_nnodes(h->node);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_clear(<PREFIX>_<NAME>_h h)
+{
+  if (h == nullptr) {
+    _E("Invalid parameter");
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+  }
+
+  g_tree_remove_all(h->node);
+
+  return RPC_PORT_ERROR_NONE;
+}
+)__c_cb";
+
+/**
+ * <KEY> The name of the key.
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_SET_UNIT_MAP_KEY_WRITE_PTR_TYPE[] =
+R"__c_cb(
+rpc_port_unit_map_write_<KEY>(info->map, name, (<KEY_TYPE>)key);
+)__c_cb";
+
+/**
+ * <KEY> The name of the key.
+ * <KEY_TYPE> The pointer type of the key.
+ */
+constexpr const char CB_SET_UNIT_MAP_KEY_WRITE_BASE_TYPE[] =
+R"__c_cb(
+rpc_port_unit_map_write_<KEY>(info->map, name, *(<KEY_TYPE> *)key);
+)__c_cb";
+
+/**
+ * <KEY> The name of the key.
+ */
+constexpr const char CB_SET_UNIT_MAP_KEY_READ[] =
+R"__c_cb(
+rpc_port_unit_map_read_<KEY>(map, name, &key);
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_SET_COMPARE_KEY_VARS_DEF_PTR_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> key_a = (<KEY_TYPE>)a;
+<KEY_TYPE> key_b = (<KEY_TYPE>)b;
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_SET_COMPARE_KEY_VARS_DEF_BASE_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> key_a = *(<KEY_TYPE> *)a;
+<KEY_TYPE> key_b = *(<KEY_TYPE> *)b;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ */
+constexpr const char CB_SET_USER_DEFINED_FREE_FUNC[] =
+R"__c_cb(<PREFIX>_<NAME>_destroy)__c_cb";
+
+constexpr const char CB_SET_BUNDLE_FREE_FUNC[] =
+R"__c_cb(bundle_free)__c_cb";
+
+constexpr const char CB_SET_FREE_FUNC[] =
+R"__c_cb(free)__c_cb";
+
+constexpr const char CB_SET_HANDLE_KEY_NULL_CHECK[] =
+R"__c_cb(h == nullptr || key == nullptr)__c_cb";
+
+constexpr const char CB_SET_HANDLE_KEY_EXIST_NULL_CHECK[] =
+R"__c_cb(h == nullptr || key == nullptr || exist == nullptr)__c_cb";
+
+constexpr const char CB_SET_HANDLE_EXIST_NULL_CHECK[] =
+R"__c_cb(h == nullptr || exist == nullptr)__c_cb";
+
+constexpr const char CB_SET_HANDLE_NULL_CHECK[] =
+R"__c_cb(h == nullptr)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the user defined type.
+ * <NAME> The name of the user defined type.
+ */
+constexpr const char CB_SET_INSERT_KEY_USER_DEFINED_IMPL[] =
+R"__c_cb(
+<PREFIX>_<NAME>_h new_key = nullptr;
+int ret = <PREFIX>_<NAME>_clone(key, &new_key);
+if (ret != RPC_PORT_ERROR_NONE)
+  return ret;
+
+g_tree_replace(h->node, (gpointer)new_key, nullptr);
+)__c_cb";
+
+constexpr const char CB_SET_INSERT_KEY_BUNDLE_IMPL[] =
+R"__c_cb(
+bundle *new_key = bundle_dup(key);
+if (new_key == nullptr) {
+  _E("bundle_dup() is failed");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+g_tree_replace(h->node, (gpointer)new_key, nullptr);
+)__c_cb";
+
+constexpr const char CB_SET_INSERT_KEY_STRING_IMPL[] =
+R"__c_cb(
+char *new_key = strdup(key);
+if (new_key == nullptr) {
+  _E("strdup() is failed");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+g_tree_replace(h->node, (gpointer)new_key, nullptr);
+)__c_cb";
+
+/**
+ * <KEY_TYPE The type of the key.
+ */
+constexpr const char CB_SET_INSERT_KEY_BASE_IMPL[] =
+R"__c_cb(
+<KEY_TYPE> *new_key = malloc(sizeof(<KEY_TYPE>));
+if (new_key == nullptr) {
+  _E("malloc() is failed");
+  return RPC_PORT_ERROR_OUT_OF_MEMORY;
+}
+
+*new_key = key;
+g_tree_replace(h->node, (gpointer)new_key, nullptr);
+)__c_cb";
+
+constexpr const char CB_SET_ERASE_KEY_PTR_TYPE[] =
+R"__c_cb(
+if (!g_tree_remove(h->node, (gpointer)key))
+  _W("g_tree_remove() is failed");
+)__c_cb";
+
+constexpr const char CB_SET_ERASE_KEY_BASE_TYPE[] =
+R"__c_cb(
+if (!g_tree_remove(h->node, &key))
+  _W("g_tree_remove() is failed");
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_SET_FOREACH_VARS_DEF_KEY_PTR_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> tmp_key = (<KEY_TYPE>)key;
+)__c_cb";
+
+/**
+ * <KEY_TYPE> The type of the key.
+ */
+constexpr const char CB_SET_FOREACH_VARS_DEF_KEY_BASE_TYPE[] =
+R"__c_cb(
+<KEY_TYPE> tmp_key = *(<KEY_TYPE> *)key;
+)__c_cb";
+
+constexpr const char CB_SET_CONTAINS_KEY_PTR_TYPE[] =
+R"__c_cb(
+data = g_tree_lookup(h->node, (gpointer)key);
+*exist = (data != nullptr) ? true : false;
+)__c_cb";
+
+constexpr const char CB_SET_CONTAINS_KEY_BASE_TYPE[] =
+R"__c_cb(
+data = g_tree_lookup(h->node, &key);
+*exist = (data != nullptr) ? true : false;
+)__c_cb";
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_C_BODY_GENERATOR_SET_BASE_CB_HH_
index f46027a..6d4d1fc 100644 (file)
@@ -24,6 +24,8 @@
 #include "idlc/gen/version2/c_header_generator_array_base_cb.hh"
 #include "idlc/gen/version2/c_header_generator_base_cb.hh"
 #include "idlc/gen/version2/c_header_generator_list_base_cb.hh"
+#include "idlc/gen/version2/c_header_generator_map_base_cb.hh"
+#include "idlc/gen/version2/c_header_generator_set_base_cb.hh"
 
 namespace tidl {
 namespace version2 {
@@ -78,10 +80,44 @@ void CHeaderGeneratorBase::GenStructureListBase(std::ofstream& stream,
 
 void CHeaderGeneratorBase::GenStructureMapBase(std::ofstream& stream,
     const Structure& st) {
+  auto iter = st.GetElements().begin();
+  if (std::next(iter) == st.GetElements().end())
+    return;
+
+  auto& key_elm = *iter;
+  auto& key_type = key_elm->GetType();
+  auto key_param_type = GetParamTypeString(ParameterType::Direction::IN,
+      key_type);
+  auto& value_elm = *(std::next(iter));
+  auto& value_type = value_elm->GetType();
+  auto value_param_type = GetParamTypeString(ParameterType::Direction::IN,
+      value_type);
+  auto value_param_type_out = GetParamTypeString(ParameterType::Direction::OUT,
+      value_type);
+
+  ReplaceAll(CB_STRUCTURE_MAP_BASE)
+      .Change("<PREFIX>", GetHandlePrefix())
+      .Change("<NAME>", st.GetID())
+      .Change("<KEY_PARAM_TYPE>", key_param_type)
+      .Change("<VALUE_PARAM_TYPE>", value_param_type)
+      .Change("<VALUE_PARAM_TYPE_OUT>", value_param_type_out)
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
 }
 
 void CHeaderGeneratorBase::GenStructureSetBase(std::ofstream& stream,
     const Structure& st) {
+  auto& elm = *(st.GetElements().begin());
+  auto& key_type = elm->GetType();
+  auto key_param_type = GetParamTypeString(ParameterType::Direction::IN,
+      key_type);
+
+  ReplaceAll(CB_STRUCTURE_SET_BASE)
+      .Change("<PREFIX>", GetHandlePrefix())
+      .Change("<NAME>", st.GetID())
+      .Change("<KEY_PARAM_TYPE>", key_param_type)
+      .Transform([&](std::string code) { return SmartIndent(code); })
+      .Out(stream);
 }
 
 void CHeaderGeneratorBase::GenStructureBase(std::ofstream& stream,
diff --git a/idlc/gen/version2/c_header_generator_map_base_cb.hh b/idlc/gen/version2/c_header_generator_map_base_cb.hh
new file mode 100644 (file)
index 0000000..32a9697
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDLC_GEN_VERSION2_C_HEADER_GENERATOR_MAP_BASE_CB_HH_
+#define IDLC_GEN_VERSION2_C_HEADER_GENERATOR_MAP_BASE_CB_HH_
+
+namespace tidl {
+namespace version2 {
+
+/**
+ * <PREFIX> The prefix of the map structure.
+ * <NAME> The name of the map structure.
+ * <KEY_PARAM_TYPE> The parameter type of the key of the map structure.
+ * <VALUE_PARAM_TYPE> The parameter type of the value of the map structure.
+ * <VALUE_PARAM_TYPE_OUT> The output parameter type of the value of the map structure.
+ */
+constexpr const char CB_STRUCTURE_MAP_BASE[] =
+R"__c_cb(
+
+/**
+ * @brief Called to compare the keys in the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] a A key
+ * @param[in] b B key
+ * @param[in] user_data The user data passed from the registration function
+ * @return Nagative value if a < b,
+ *         zero if a = b,
+ *         positive value if a > b.
+ * @see <PREFIX>_<NAME>_set_compare_cb()
+ */
+typedef int (*<PREFIX>_<NAME>_compare_cb)(<KEY_PARAM_TYPE>a, <KEY_PARAM_TYPE>b, void *user_data);
+
+/**
+ * @brief Called to retrieve the key/value contained in the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a value MUST NOT be released by the application.
+ * @param[in] key The key of the map
+ * @param[in] value The value of the map
+ * @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>_foreach_cb)(<KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE>value, void *user_data);
+
+/**
+ * @brief Sets the comparision callback function for the <PREFIX>_<NAME> handle.
+ * @details The <PREFIX>_<NAME> uses the registered callback function.
+ *          If it's not set, calling the <PREFIX>_<NAME>_create() returns a negative error value.
+ *
+ * @param[in] callback The comparison callback function
+ * @param[in] user_data The user data to be passed to the comparision 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>_create()
+ */
+int <PREFIX>_<NAME>_set_compare_cb(<PREFIX>_<NAME>_compare_cb callback, 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_NONE Internal I/O error
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_set_compare_cb()
+ * @see <PREFIX>_<NAME>_destroy()
+ * @pre <PREFIX>_<NAME>_set_compare_cb()
+ */
+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 Inserts the key/value into the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a key and the @a value are copied internally.
+ *          If you do the key data comparison based on the address, it makes a problem.
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] key The key to insert.
+ * @param[in] value The value corresponding to the key.
+ * @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>_erase()
+ */
+int <PREFIX>_<NAME>_insert(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE>value);
+
+/**
+ * @brief Gets the value corresponding to the given key.
+ *
+ * @remarks The @c value is copied internally. The data being returned is not a reference value.
+ *          You should release it if it's no longer needed. The value such as integer does not need to be released.
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] key The key to look up.
+ * @param[out] value The value correspoding to the key.
+ * @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>_lookup(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE_OUT>value);
+
+/**
+ * @breif Removes the key/value pair from the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] key The key to remove.
+ * @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>_erase(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key);
+
+/**
+ * @brief Inserts the key/value into the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a key and the @a value are copied internally.
+ *          If you do the key data comparison based on the address, it makes a problem.
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] key The key to insert.
+ * @param[in] value The value corresponding to the key.
+ * @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>_insert()
+ */
+int <PREFIX>_<NAME>_replace(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, <VALUE_PARAM_TYPE>value);
+
+/**
+ * @brief Retrieves all values contained in the <PREFIX>_<NAME> handle.
+ * @details This function called <PREFIX>_<NAME>_foreach_cb once for each the key/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>_foreach_cb()
+ */
+int <PREFIX>_<NAME>_foreach(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_foreach_cb callback, void *user_data);
+
+/**
+ * @brief Checks whether the key exists or not.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] key The key to check.
+ * @param[out] exist If it's true, the key exists.
+ * @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>_contains(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, bool *exist);
+
+/**
+ * @brief Gets the number of elements in the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] size 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>_size(<PREFIX>_<NAME>_h h, size_t *size);
+
+/**
+ * @brief Removes all elements from 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
+ */
+int <PREFIX>_<NAME>_clear(<PREFIX>_<NAME>_h h);
+)__c_cb";
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_C_HEADER_GENERATOR_MAP_BASE_CB_HH_
diff --git a/idlc/gen/version2/c_header_generator_set_base_cb.hh b/idlc/gen/version2/c_header_generator_set_base_cb.hh
new file mode 100644 (file)
index 0000000..8def387
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDLC_GEN_VERSION2_C_HEADER_GENERATOR_SET_BASE_CB_HH_
+#define IDLC_GEN_VERSION2_C_HEADER_GENERATOR_SET_BASE_CB_HH_
+
+namespace tidl {
+namespace version2 {
+
+/**
+ * <PREFIX> The prefix of the set structure.
+ * <NAME> The name of the set structure.
+ * <KEY_PARAM_TYPE> The parameter type of the key of the set structure.
+ */
+constexpr const char CB_STRUCTURE_SET_BASE[] =
+R"__c_cb(
+
+/**
+ * @brief Called to compare the keys in the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] a A key
+ * @param[in] b B key
+ * @param[in] user_data The user data passed from the registration function
+ * @return Nagative value if a < b,
+ *         zero if a = b,
+ *         positive value if a > b.
+ * @see <PREFIX>_<NAME>_set_compare_cb()
+ */
+typedef int (*<PREFIX>_<NAME>_compare_cb)(<KEY_PARAM_TYPE>a, <KEY_PARAM_TYPE>b, void *user_data);
+
+/**
+ * @brief Called to retrieve the key contained in the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a value MUST NOT be released by the application.
+ * @param[in] key The key of the map
+ * @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>_foreach_cb)(<KEY_PARAM_TYPE>key, void *user_data);
+
+/**
+ * @brief Sets the comparision callback function for the <PREFIX>_<NAME> handle.
+ * @details The <PREFIX>_<NAME> uses the registered callback function.
+ *          If it's not set, calling the <PREFIX>_<NAME>_create() returns a negative error value.
+ *
+ * @param[in] callback The comparison callback function
+ * @param[in] user_data The user data to be passed to the comparison 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>_create()
+ */
+int <PREFIX>_<NAME>_set_compare_cb(<PREFIX>_<NAME>_compare_cb callback, 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_IO_ERROR Internal I/O error
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory
+ * @see <PREFIX>_<NAME>_set_compare_cb()
+ * @see <PREFIX>_<NAME>_destroy()
+ * @pre <PREFIX>_<NAME>_set_compare_cb()
+ */
+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 Inserts the key into the <PREFIX>_<NAME> handle.
+ *
+ * @remarks The @a key is copied internally.
+ *          If you do the key data comparison based on the address, it makes a problem.
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] key The key to insert.
+ * @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>_erase()
+ */
+int <PREFIX>_<NAME>_insert(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key);
+
+/**
+ * @breif Removes the key from the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle.
+ * @param[in] key The key to remove.
+ * @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>_erase(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key);
+
+/**
+ * @brief Retrieves all keys contained in the <PREFIX>_<NAME> handle.
+ * @details This function called <PREFIX>_<NAME>_foreach_cb once for each the key 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>_foreach_cb()
+ */
+int <PREFIX>_<NAME>_foreach(<PREFIX>_<NAME>_h h, <PREFIX>_<NAME>_foreach_cb callback, void *user_data);
+
+/**
+ * @brief Checks whether the key exists or not.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[in] key The key to check.
+ * @param[out] exist If it's true, the key exists.
+ * @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>_contains(<PREFIX>_<NAME>_h h, <KEY_PARAM_TYPE>key, bool *exist);
+
+/**
+ * @brief Gets the number of elements in the <PREFIX>_<NAME> handle.
+ *
+ * @param[in] h The <PREFIX>_<NAME> handle
+ * @param[out] size 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>_size(<PREFIX>_<NAME>_h h, size_t *size);
+
+/**
+ * @brief Removes all elements from 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
+ */
+int <PREFIX>_<NAME>_clear(<PREFIX>_<NAME>_h h);
+)__c_cb";
+
+}  // namespace version2
+}  // namespace tidl
+
+#endif  // IDLC_GEN_VERSION2_C_HEADER_GENERATOR_SET_BASE_CB_HH_
index 4a7b35b..7840d08 100644 (file)
@@ -1075,7 +1075,7 @@ constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_READ[] =
 R"__c_cb(
 res_ = rpc_port_unit_map_read_<TYPE_NAME>(map_, "<ARG_NAME>", &<ARG>);
 if (res_ != RPC_PORT_ERROR_NONE) {
-  _E("Failed to read <TYPE_NAME>. error(%d)", res);
+  _E("Failed to read <TYPE_NAME>. error(%d)", res_);
   rpc_port_unit_map_destroy(map_);
   break;
 }