From: Hwankyu Jhun Date: Wed, 18 Aug 2021 06:54:24 +0000 (+0900) Subject: Refactor C Generator X-Git-Tag: submit/tizen/20210910.110629~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=728c992b56e13c40df1c4402d772a6e95102dc05;p=platform%2Fcore%2Fappfw%2Ftidl.git Refactor C Generator - Fixes code block for readability - Fixes some APIs to support container type - Adds new APIs for consistency with C++ Generator - Renames the APIs - Adds annotations to functions of header files. Change-Id: I3a7afb069d80985f88562a0ef1b3ce07229440dc Signed-off-by: Hwankyu Jhun --- diff --git a/idlc/CMakeLists.txt b/idlc/CMakeLists.txt index 6b3f69fd..375f58da 100644 --- a/idlc/CMakeLists.txt +++ b/idlc/CMakeLists.txt @@ -17,7 +17,7 @@ ENDIF(DEFINED BUILD_WIN) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wno-unused-function -Wno-sign-compare") SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++11") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -std=c++14") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc") SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") diff --git a/idlc/gen/c_body_gen_array_base_cb.h b/idlc/gen/c_body_gen_array_base_cb.h new file mode 100644 index 00000000..e152a7d2 --- /dev/null +++ b/idlc/gen/c_body_gen_array_base_cb.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_C_GEN_C_BODY_GEN_ARRAY_BASE_CB_H_ +#define IDLC_C_GEN_C_BODY_GEN_ARRAY_BASE_CB_H_ + +/** + * The prefix of the array structure. + * The name of the array structure. + * The type of the element of the array. + */ +constexpr const char CB_STRUCTURE_ARRAY_DEF[] = +R"__c_cb( +typedef struct __s { + rpc_port_parcelable_t parcelable; + *value; + int size; +} __t; +)__c_cb"; + +/** + * The prefix of the array structure. + * The name of the array structure. + * The implementation to write the value to the parcel. + * The implemention to read the value from the parcel. + * The type of the input parameter. + * The type of the output parameter. + * The type of the element of the array. + * The size of the type of the element. + * The implementation to release elements. + */ +constexpr const char CB_STRUCTURE_ARRAY_BASE[] = +R"__c_cb( +static void ____to(rpc_port_parcel_h parcel, void *data) +{ + __h h = data; + int i; + + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + return; + } + + rpc_port_parcel_write_array_count(parcel, h->size); + + for (i = 0; i < h->size; ++i) + +} + +static void ____from(rpc_port_parcel_h parcel, void *data) +{ + __h h = data; + value; + int ret; + int i; + + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + ret = rpc_port_parcel_read_array_count(parcel, &h->size); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read array count. error(%d)", ret); + set_last_result(ret); + return; + } + + h->value = calloc(h->size, sizeof()); + if (h->value == nullptr) { + _E("Out of memory"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + for (i = 0; i < h->size; ++i) { + + } + + set_last_result(RPC_PORT_ERROR_NONE); +} + +int __create(__h *h) +{ + __t *handle; + + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + handle = calloc(1, sizeof(__t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + handle->parcelable.to = ____to; + handle->parcelable.from = ____from; + + *h = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __destroy(__h h) +{ + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + + + free(h); + + return RPC_PORT_ERROR_NONE; +} + +int __clone(__h h, __h *clone) +{ + __h handle; + rpc_port_parcel_h parcel; + int ret; + + if (h == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret = __create(&handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + return ret; + } + + ret = rpc_port_parcel_create(&parcel); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret); + __destroy(handle); + return ret; + } + + rpc_port_parcel_write(parcel, &h->parcelable, h); + rpc_port_parcel_read(parcel, &handle->parcelable, handle); + ret = get_last_result(); + rpc_port_parcel_destroy(parcel); + + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", ret); + __destroy(handle); + return ret; + } + + *clone = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __set(__h h, *value, int size) +{ + __h handle; + __h clone; + int ret; + + if (h == nullptr || value == nullptr || size <= 0) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret = __create(&handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + return ret; + } + + handle->value = (*)value; + handle->size = size; + + ret = __clone(handle, &clone); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to clone handle. error(%d)", ret); + handle->value = nullptr; + handle->size = 0; + __destroy(handle); + return ret; + } + + handle->value = h->value; + handle->size = h->size; + __destroy(handle); + + h->value = clone->value; + h->size = clone->size; + + clone->value = nullptr; + clone->size = 0; + __destroy(clone); + + return RPC_PORT_ERROR_NONE; +} + +int __get(__h h, *value, int *size) +{ + __h handle; + int ret; + + if (h == nullptr || value == nullptr || size == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret = __clone(h, &handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to clone handle. error(%d)", ret); + return ret; + } + + *value = handle->value; + *size = handle->size; + + handle->value = nullptr; + handle->size = 0; + __destroy(handle); + + return RPC_PORT_ERROR_NONE; +} +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write(parcel, &h->value[i]->parcelable, h->value[i]); +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_bundle(parcel, h->value[i]); +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel, STRING_GET(h->value[i])); +)__c_cb"; + +/** + * The type of the parcel of the value. + */ +constexpr const char CB_STRUCTURE_ARRAY_BASE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_(parcel, h->value[i]); +)__c_cb"; + +/** + * The prefix of the user-defined type. + * The name of the user-defined type. + */ +constexpr const char CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_READ[] = +R"__c_cb( +ret = __create(&value); +if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + set_last_result(ret); + return; +} + +rpc_port_parcel_read(parcel, &value->parcelable, value); +if (get_last_result() != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", get_last_result()); + __destroy(value); + return; +} + +h->value[i] = value; +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_READ[] = +R"__c_cb( +value = nullptr; +rpc_port_parcel_read_bundle(parcel, &value); +if (value == nullptr) { + _E("Failed to read data"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; +} + +h->value[i] = value; +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_STRING_PARCEL_READ[] = +R"__c_cb( +value = nullptr; +rpc_port_parcel_read_string(parcel, &value); +if (value == nullptr) { + _E("Failed to read data"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; +} + +h->value[i] = value; +)__c_cb"; + +/** + * The type of the parcel of the value. + */ +constexpr const char CB_STRUCTURE_ARRAY_BASE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_(parcel, &value); +h->value[i] = value; +)__c_cb"; + +/** + * The prefix of the element type. + * The name of the element type. + */ +constexpr const char CB_STRUCTURE_ARRAY_USER_DEFINED_FREE[] = +R"__c_cb( +if (h->value) { + for (int i = 0; i < h->size; ++i) { + if (h->value[i]) + __destroy(h->value[i]); + } + + free(h->value); +} +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_BUNDLE_FREE[] = +R"__c_cb( +if (h->value) { + for (int i = 0; i < h->size; ++i) { + if (h->value[i]) + bundle_free(h->value[i]); + } + + free(h->value); +} +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_STRING_FREE[] = +R"__c_cb( +if (h->value) { + for (int i = 0; i < h->size; ++i) { + if (h->value[i]) + free(h->value[i]); + } + + free(h->value); +} +)__c_cb"; + +constexpr const char CB_STRUCTURE_ARRAY_BASE_FREE[] = +R"__c_cb( +if (h->value) + free(h->value); +)__c_cb"; + +#endif // IDLC_C_GEN_C_BODY_GEN_ARRAY_BASE_CB_H_ diff --git a/idlc/gen/c_body_gen_base.cc b/idlc/gen/c_body_gen_base.cc index 8d1273e9..d270a5ac 100644 --- a/idlc/gen/c_body_gen_base.cc +++ b/idlc/gen/c_body_gen_base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,19 +14,20 @@ * limitations under the License. */ +#include #include +#include "idlc/gen/c_body_gen_array_base_cb.h" #include "idlc/gen/c_body_gen_base.h" - -namespace { #include "idlc/gen/c_body_gen_base_cb.h" -} +#include "idlc/gen/c_body_gen_list_base_cb.h" namespace tidl { CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr doc) : CGeneratorBase(doc) { parcel_type_map_ = { + {"none", ""}, {"char", "byte"}, {"int", "int32"}, {"short", "int16"}, @@ -38,1242 +39,720 @@ CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr doc) {"bundle", "bundle"}, {"file", "string"}, }; -} -void CBodyGeneratorBase::GenStructures(std::ofstream& stream) { - for (auto& i : GetDocument().GetBlocks()) { - if (i->GetType() == Block::TYPE_STRUCTURE) { - const Structure &st = static_cast(*i); - GenStructure(stream, st); - for (auto& j : st.GetElements().GetElms()) { - auto& t = j->GetType(); - AddStructureFromType(t); + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() == Block::TYPE_STRUCTURE) { + auto& st = static_cast(*b); + for (auto& e : st.GetElements().GetElms()) { + auto& type = e->GetType(); + AddStructureFromType(type); } } else { - const Interface &inf = static_cast(*i); + auto& inf = static_cast(*b); for (auto& d : inf.GetDeclarations().GetDecls()) { for (auto& p : d->GetParameters().GetParams()) { - if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) + auto& type = p->GetParameterType().GetBaseType(); + if (IsDelegateType(inf, type)) continue; - AddStructureFromType(p->GetParameterType().GetBaseType()); + + AddStructureFromType(type, inf); } } } } - - for (auto& p : GetStructures()) { - const Structure& st = *p.second; - GenStructure(stream, st); - } } -void CBodyGeneratorBase::GenStructure(std::ofstream& stream, - const Structure& st) { - GenStructureDeclaration(stream, st); - GenStructureParcelSerializer(stream, st); - GenStructureParcelDeserializer(stream, st); - GenStructureConstructor(stream, st); - GenStructureDestructor(stream, st); - GenStructureCloner(stream, st); - GenStructureSetter(stream, st); - GenStructureGetter(stream, st); - GenStructureIterator(stream, st); - GenStructureRemover(stream, st); - GenStructureLengthGetter(stream, st); +void CBodyGeneratorBase::GenIncludeHeader(std::ofstream& stream) { + std::string code; + code += "#include \""; + code += FileName.substr(0, FileName.length() - 2); + code += ".h\""; + stream << NLine(1); + stream << code; + stream << NLine(1); } -void CBodyGeneratorBase::GenStructureDeclaration(std::ofstream& stream, - const Structure& st) { - stream << SmartIndent(GenTemplateString(CB_STRUCT_DECL, - [&]()->std::string { - return st.GetComments(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - std::string str; - for (auto& i : st.GetElements().GetElms()) { - str += NLine(1) + GetStringFromElementType(i->GetType()) + - i->GetID() + ";"; - if (i->GetType().ToString() == "array") - str += NLine(1) + "int " + i->GetID() + "_size;"; - } - return str; - })); +void CBodyGeneratorBase::GenLogTag(std::ofstream& stream, + const std::string& log_tag) { + std::string code = ReplaceAll(CB_LOG_TAG, "", log_tag); + stream << code; } -void CBodyGeneratorBase::GenStructureParcelSerializer(std::ofstream& stream, - const Structure& st) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_STRUCT_SERIALIZER, "##", GetStructIdWithNamespace(st)), - [&]()->std::string { - std::string str; - for (auto& i : st.GetElements().GetElms()) { - str += NLine(1); - str += GetParcelWriteString(i->GetID(), i->GetType()); - } - return str; - })); +void CBodyGeneratorBase::GenLogDefinition(std::ofstream& stream) { + stream << SmartIndent(CB_LOG_DEF); } -void CBodyGeneratorBase::GenStructureParcelDeserializer(std::ofstream& stream, - const Structure& st) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_STRUCT_DESERIALIZER, "##", GetStructIdWithNamespace(st)), - [&]()->std::string { - std::string str; - for (auto& i : st.GetElements().GetElms()) { - str += NLine(1); - str += GetParcelReadString(i->GetID(), i->GetType()); - } - return str; - })); +void CBodyGeneratorBase::GenBaseDefinition(std::ofstream& stream) { + stream << SmartIndent(CB_BASE_DEF); } -void CBodyGeneratorBase::GenStructureConstructor(std::ofstream& stream, - const Structure& st) { - stream << SmartIndent(ReplaceAll(CB_STRUCT_CTOR, "##", - GetStructIdWithNamespace(st))); -} +void CBodyGeneratorBase::GenStructureDefs(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() == Block::TYPE_STRUCTURE) { + auto& st = static_cast(*b); + GenStructureDef(stream, st); + } + } -void CBodyGeneratorBase::GenStructureDestructor(std::ofstream& stream, - const Structure& st) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_STRUCT_DTOR, "##", - GetStructIdWithNamespace(st)), - [&]()->std::string { - std::string str; - for (auto& i : st.GetElements().GetElms()) { - str += GetFinalizeString(i->GetID(), i->GetType(), "h->"); - } - return str; - })); + for (auto& i : GetStructures()) { + auto& st = i.second; + GenStructureDef(stream, *st); + } } -void CBodyGeneratorBase::GenStructureSetter(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - stream << SmartIndent(GenTemplateString(CB_STRUCT_SETTER, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().ToString() == "list") - return "add"; - return "set"; - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().IsUserDefinedType()) - return GetParcelParamTypeString(i->GetType()); - - if (i->GetType().ToString() == "list") { - if (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array") { - return GetParcelParamTypeString(*i->GetType().GetMetaType()); - } else { - return ConvertTypeToString(ParameterType::Direction::IN, - *i->GetType().GetMetaType()); - } - } - - if (i->GetType().ToString() == "array") { - return GetStringFromElementType(i->GetType()); - } - - return ConvertTypeToString(ParameterType::Direction::IN, - i->GetType()); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") { - std::string str; - str += i->GetID(); - str += ", "; - str += "int " + i->GetID() + "_size"; - return str; - } - return i->GetID(); - }, - [&]()->std::string { - if ((i->GetType().IsUserDefinedType() || - i->GetType().ToString() == "string" || - i->GetType().ToString() == "bundle" || - i->GetType().ToString() == "file") || - ((i->GetType().ToString() == "list" || - i->GetType().ToString() == "array") && - (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array" || - i->GetType().GetMetaType()->ToString() == "string" || - i->GetType().GetMetaType()->ToString() == "bundle" || - i->GetType().GetMetaType()->ToString() == "file"))) - return "!h || !" + i->GetID(); - - return "!h"; - }, - [&]()->std::string { - std::string str; - str += NLine(1); - str += GetSetterString(i->GetID(), i->GetType()); - return str; - })); - } +void CBodyGeneratorBase::GenStructureDef(std::ofstream& stream, + const Structure& st) { + if (st.GetID().compare(0, strlen("array"), "array") == 0) + GenStructureArrayDef(stream, st); + else if (st.GetID().compare(0, strlen("list"), "list") == 0) + GenStructureListDef(stream, st); + else + GenStructureBaseDef(stream, st); } -void CBodyGeneratorBase::GenStructureGetter(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() == "list") - continue; +// @see #CB_STRUCTURE_ARRAY_DEF +void CBodyGeneratorBase::GenStructureArrayDef(std::ofstream& stream, + const Structure& st) { + std::string code = ReplaceAll(CB_STRUCTURE_ARRAY_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", st.GetID()); - stream << SmartIndent(GenTemplateString(CB_STRUCT_GETTER, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") - return GetStringFromElementType(i->GetType()) + "*"; - - return ConvertTypeToString(ParameterType::Direction::OUT, - i->GetType()); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") { - std::string str; - str += i->GetID(); - str += ", "; - str += "int *" + i->GetID() + "_size"; - return str; - } - return i->GetID(); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") { - std::string str; - str += "!"; - str += i->GetID(); - str += " || "; - str += "!" + i->GetID() + "_size"; - return str; - } - return "!" + i->GetID(); - }, - [&]()->std::string { - std::string str; - str += NLine(1); - str += GetGetterString(i->GetID(), i->GetType()); - return str; - })); - } + auto& elm = st.GetElements().GetElms().front(); + auto& type = elm->GetType(); + auto element_type = GetDataTypeString(type, false); + code = ReplaceAll(code, "", element_type); + + stream << SmartIndent(code); } -void CBodyGeneratorBase::GenStructureIterator(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() != "list") - continue; +// @see #CB_STRUCTURE_LIST_DEF +void CBodyGeneratorBase::GenStructureListDef(std::ofstream& stream, + const Structure& st) { + std::string code = ReplaceAll(CB_STRUCTURE_LIST_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", st.GetID()); - stream << SmartIndent(GenTemplateString(CB_STRUCT_ITERATOR, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array") - return GetParcelParamTypeString(*i->GetType().GetMetaType()); - - return ConvertTypeToString(ParameterType::Direction::IN, - *i->GetType().GetMetaType()); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - std::string str; - str += NLine(1); - str += GetIteratorString(i->GetID(), i->GetType()); - return str; - })); - } + stream << SmartIndent(code); } -void CBodyGeneratorBase::GenStructureRemover(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() != "list") - continue; +// @see #CB_STRUCTURE_BASE_DEF +void CBodyGeneratorBase::GenStructureBaseDef(std::ofstream& stream, + const Structure& st) { + std::string code = ReplaceAll(CB_STRUCTURE_BASE_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", st.GetID()); - stream << SmartIndent(GenTemplateString(CB_STRUCT_REMOVER, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - if (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array" || - i->GetType().GetMetaType()->ToString() == "string" || - i->GetType().GetMetaType()->ToString() == "bundle" || - i->GetType().GetMetaType()->ToString() == "file") - return GetParcelParamTypeString(*i->GetType().GetMetaType()); - - return ConvertTypeToString(ParameterType::Direction::IN, - *i->GetType().GetMetaType(), false); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - std::string str; - - if (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array") { - str = GetHandlePrefix() - + GetFullNameFromType(*i->GetType().GetMetaType()) - + "_destroy(value);"; - } else { - str = GetFinalizeString("value", *i->GetType().GetMetaType(), ""); - } - - if (str == "") - return "free(value);\n"; - return str; - })); - } + auto& elms = st.GetElements(); + code = ReplaceAll(code, "", GenBaseElements(elms)); + + stream << SmartIndent(code); } -void CBodyGeneratorBase::GenStructureLengthGetter(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() != "list") - continue; +void CBodyGeneratorBase::GenStructures(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() == Block::TYPE_STRUCTURE) { + auto& st = static_cast(*b); + GenStructure(stream, st); + } + } - stream << SmartIndent(GenTemplateString(CB_STRUCT_LENGTH_GETTER, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - })); + for (auto& i : GetStructures()) { + auto& st = i.second; + GenStructure(stream, *st); } } -void CBodyGeneratorBase::GenStructureCloner(std::ofstream& stream, - const Structure& st) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_STRUCT_CLONER, "##", GetStructIdWithNamespace(st)), - [&]()->std::string { - std::string str; - for (auto& i : st.GetElements().GetElms()) { - str += NLine(1); - str += GetClonerString(i->GetID(), i->GetType(), st); - } - return str; - })); -} +void CBodyGeneratorBase::GenStructure(std::ofstream& stream, + const Structure& st) { + if (st.GetID().compare(0, strlen("array"), "array") == 0) + GenStructureArrayBase(stream, st); + else if (st.GetID().compare(0, strlen("list"), "list") == 0) + GenStructureListBase(stream, st); + else + GenStructureBase(stream, st); +} + +// @see #CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_WRITE +// @see #CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_WRITE +// @see #CB_STRUCTURE_ARRAY_STRING_PARCEL_WRITE +// @see #CB_STRUCTURE_ARRAY_BASE_PARCEL_WRITE +std::string CBodyGeneratorBase::GenArrayParcelWrite( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + code = std::string(CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_WRITE); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_WRITE); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = std::string(CB_STRUCTURE_ARRAY_STRING_PARCEL_WRITE); + } else { + code = ReplaceAll(CB_STRUCTURE_ARRAY_BASE_PARCEL_WRITE, "", + GetParcelType(type)); + } -std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type, - bool meta_type) { - if (type.IsUserDefinedType()) - return ""; + return RemoveLine(code); +} - if (type.ToString() == "list" || +// @see #CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_READ +// @see #CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_READ +// @see #CB_STRUCTURE_ARRAY_STRING_PARCEL_READ +// @see #CB_STRUCTURE_ARRAY_BASE_PARCEL_READ +std::string CBodyGeneratorBase::GenArrayParcelRead( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || type.ToString() == "array") { - if (meta_type) - return ""; - return "array_count"; + code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + + std::string name; + auto* meta_type = type.GetMetaType(); + if (meta_type == nullptr) + name = type.ToString(); + else + name = GetFullNameFromType(*meta_type); + + code = ReplaceAll(code, "", name); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_ARRAY_BUNDLE_PARCEL_READ); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = std::string(CB_STRUCTURE_ARRAY_STRING_PARCEL_READ); + } else { + code = ReplaceAll(CB_STRUCTURE_ARRAY_BASE_PARCEL_READ, "", + GetParcelType(type)); } - return parcel_type_map_[type.ToString()]; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetParcelWriteFunctionString( - const BaseType& type, bool meta_type) { - std::string str = "rpc_port_parcel_write"; - std::string parcel_type = GetParcelTypeString(type, meta_type); - if (parcel_type != "") - str += "_" + parcel_type; +// @see #CB_STRUCTURE_ARRAY_USER_DEFINED_FREE +// @see #CB_STRUCTURE_ARRAY_BUNDLE_FREE +// @see #CB_STRUCTURE_ARRAY_STRING_FREE +// @see #CB_STRUCTURE_ARRAY_BASE_FREE +std::string CBodyGeneratorBase::GenArrayElementsFree( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + code = ReplaceAll(CB_STRUCTURE_ARRAY_USER_DEFINED_FREE, "", + GetHandlePrefix()); - return str; -} + std::string name; + auto* meta_type = type.GetMetaType(); + if (meta_type == nullptr) + name = type.ToString(); + else + name = GetFullNameFromType(*meta_type); -std::string CBodyGeneratorBase::GetParcelWriteString(const std::string& id, - const BaseType& type) { - std::string str; - const char parcel[] = "$$(parcel, $$);"; - const char ternary_operation[] = "## ? ## : \"\""; - - str += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelWriteFunctionString(type); - }, - [&]()->std::string { - if (type.IsUserDefinedType()) - return "&h->" + id + "->parcelable, h->" + id; - if (type.ToString() == "list") - return "g_list_length(h->" + id + ")"; - if (type.ToString() == "array") - return "h->" + id + "_size"; - if (type.ToString() == "string") - return ReplaceAll(ternary_operation, "##", "h->" + id); - return "h->" + id; - }); - - if (type.ToString() == "list") { - str += GenTemplateString(CB_WRITE_LIST_BLOCK, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - return GenTemplateString(parcel, - [&]()->std::string { - return GetParcelWriteFunctionString(*type.GetMetaType(), true); - }, - [&]()->std::string { - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") - return "&value->parcelable, value"; - if (type.GetMetaType()->ToString() == "bundle") - return "value"; - if (type.GetMetaType()->ToString() == "string" - || type.GetMetaType()->ToString() == "file") - return ReplaceAll(ternary_operation, "##", "value"); - return "*value"; - }); - }); - } else if (type.ToString() == "array") { - str += GenTemplateString(CB_WRITE_ARRAY_BLOCK, - [&]()->std::string { - return "h->" + id + "_size"; - }, - [&]()->std::string { - return GenTemplateString(parcel, - [&]()->std::string { - return GetParcelWriteFunctionString(*type.GetMetaType(), true); - }, - [&]()->std::string { - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") - return "&h->" + id + "[i]->parcelable, h->" + id +"[i]"; - if (type.GetMetaType()->ToString() == "string" || - type.GetMetaType()->ToString() == "file") - return ReplaceAll(ternary_operation, "##", "h->" + id - + "[i]"); - return "h->" + id + "[i]"; - }); - }); + code = ReplaceAll(code, "", name); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_ARRAY_BUNDLE_FREE); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = std::string(CB_STRUCTURE_ARRAY_STRING_FREE); + } else { + code = std::string(CB_STRUCTURE_ARRAY_BASE_FREE); } - return str; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetParcelReadFunctionString( - const BaseType& type, bool meta_type) { - std::string str = "rpc_port_parcel_read"; - std::string parcel_type = GetParcelTypeString(type, meta_type); - if (parcel_type != "") - str += "_" + parcel_type; +// @see #CB_STRUCTURE_ARRAY_BASE +void CBodyGeneratorBase::GenStructureArrayBase(std::ofstream& stream, + const Structure& st) { + std::string code = ReplaceAll(CB_STRUCTURE_ARRAY_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", st.GetID()); - return str; + auto& elm = st.GetElements().GetElms().front(); + code = ReplaceAll(code, "", GenArrayParcelWrite(elm)); + code = ReplaceAll(code, "", GenArrayParcelRead(elm)); + + auto& type = elm->GetType(); + auto param_type = GetParamTypeString(ParameterType::Direction::IN, type); + code = ReplaceAll(code, "", param_type); + param_type = GetParamTypeString(ParameterType::Direction::OUT, type); + code = ReplaceAll(code, "", param_type); + + auto element_type = GetDataTypeString(type, false); + code = ReplaceAll(code, "", element_type); + auto element_type_size = GetDataTypeString(type, false); + element_type_size = RemoveLastSpaces(element_type_size); + code = ReplaceAll(code, "", element_type_size); + code = ReplaceAll(code, "", GenArrayElementsFree(elm)); + + stream << SmartIndent(code); } -std::string CBodyGeneratorBase::GetParcelReadString(const std::string& id, - const BaseType& type) { - std::string str; - const char parcel[] = "$$(parcel, $$);"; - - if (type.ToString() == "list") { - str += GenTemplateString(CB_READ_LIST_BLOCK, - [&]()->std::string { - return GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(type); - }, - [&]()->std::string { - return "&len"; - }); - }, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - std::string s; - - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") { - s += GetConstructorString(*type.GetMetaType(), "value"); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!value"; - }, - [&]()->std::string { - std::string ss; - ss += "_E(\"Failed to create handle\");" + NLine(1); - ss += "return;"; - return ss; - }); - s += NLine(1); - s += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(*type.GetMetaType(), true); - }, - [&]()->std::string { - return "&value->parcelable, value"; - }); - } else if (type.GetMetaType()->ToString() == "string" || - type.GetMetaType()->ToString() == "bundle"|| - type.GetMetaType()->ToString() == "file") { - s += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(*type.GetMetaType()); - }, - [&]()->std::string { - return "&value"; - }); - } else { - s += "value = calloc(1, sizeof(*value));" + NLine(1); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!value"; - }, - [&]()->std::string { - std::string ss; - ss += "_E(\"Out of memory\");" + NLine(1); - ss += "return;"; - return ss; - }); - s += NLine(1); - s += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(*type.GetMetaType()); - }, - [&]()->std::string { - return "value"; - }); - } - - return s; - }, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - return "h->" + id; - }); - } else if (type.ToString() == "array") { - str += GenTemplateString(ReplaceAll(CB_READ_ARRAY_BLOCK, "##", id), - [&]()->std::string { - return GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(type); - }, - [&]()->std::string { - return "&h->" + id + "_size"; - }); - }, - [&]()->std::string { - return GetReturnTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - return GetErrorValue(*type.GetMetaType()); - }, - [&]()->std::string { - std::string s; - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") { - s += GetConstructorString(*type.GetMetaType(), "value"); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!value"; - }, - [&]()->std::string { - std::string ss; - ss += "_E(\"Failed to create handle\");" + NLine(1); - ss += "return;"; - return ss; - }); - s += NLine(1); - s += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(*type.GetMetaType(), true); - }, - [&]()->std::string { - return "&value->parcelable, value"; - }); - } else { - s += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(*type.GetMetaType()); - }, - [&]()->std::string { - return "&value"; - }); - } - s += NLine(1); - s += GetSetterString("h->" + id + "[i]", "value"); - return s; - }); - } else if (type.IsUserDefinedType()) { - str += GenTemplateString(ReplaceAll(CB_READ_USER_DEFINED_BLOCK, "##", id), - [&]()->std::string { - return GetFullNameFromType(type); - }); +// @see #CB_STRUCTURE_LIST_USER_DEFINED_FREE +// @see #CB_STRUCTURE_LIST_BUNDLE_FREE +// @see #CB_STRUCTURE_LIST_STRING_FREE +// @see #CB_STRUCTURE_LIST_BASE_FREE +std::string CBodyGeneratorBase::GenListDataFree( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_FREE, "", + GetHandlePrefix()); + + std::string name; + auto* meta_type = type.GetMetaType(); + if (meta_type == nullptr) + name = type.ToString(); + else + name = GetFullNameFromType(*meta_type); + + code = ReplaceAll(code, "", name); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_LIST_BUNDLE_FREE); + } else if (type.ToString() == "string" || type.ToString() == "flie") { + code = std::string(CB_STRUCTURE_LIST_STRING_FREE); } else { - str += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString(type); - }, - [&]()->std::string { - if (type.IsUserDefinedType()) - return "&h->" + id + "->parcelable, h->" + id; - return "&h->" + id; - }); + code = std::string(CB_STRUCTURE_LIST_BASE_FREE); } - return str; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetFinalizeString(const std::string& id, - const BaseType& type, const std::string& handle) { - std::string str; - - if (!type.IsUserDefinedType() && - type.ToString() != "list" && - type.ToString() != "array" && - type.ToString() != "string" && - type.ToString() != "bundle" && - type.ToString() != "file") - return str; - - if (type.ToString() == "list") { - str += GenTemplateString(CB_FINALIZE_LIST_BLOCK, - [&]()->std::string { - return handle + id; - }, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - return GenTemplateString(CB_IF_STATEMENT, - [&]()->std::string { - return "value"; - }, - [&]()->std::string { - return GetDestructorString(*type.GetMetaType(), - "value", true) + NLine(1); - }); - }, - [&]()->std::string { - return handle + id; - }); - } else if (type.ToString() == "array") { - if (!type.GetMetaType()->IsUserDefinedType() && - type.GetMetaType()->ToString() != "list" && - type.GetMetaType()->ToString() != "array" && - type.GetMetaType()->ToString() != "string" && - type.GetMetaType()->ToString() != "bundle" && - type.GetMetaType()->ToString() != "file") { - return GenTemplateString(CB_IF_STATEMENT, - [&]()->std::string { - return handle + id; - }, - [&]()->std::string { - return "free(" + handle + id + ");"; - }); - } - str += GenTemplateString(CB_FINALIZE_ARRAY_BLOCK, - [&]()->std::string { - return handle + id + "_size"; - }, - [&]()->std::string { - return GenTemplateString(CB_IF_STATEMENT, - [&]()->std::string { - return handle + id + "[j]"; - }, - [&]()->std::string { - return GetDestructorString(*type.GetMetaType(), - handle + id + "[j]", true) + NLine(1); - }); - }, - [&]()->std::string { - return handle + id; - }); +// @see #CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_WRITE +// @see #CB_STRUCTURE_LIST_BUNDLE_PARCEL_WRITE +// @see #CB_STRUCTURE_LIST_STRING_PARCEL_WRITE +// @see #CB_STRUCTURE_LIST_BASE_PARCEL_WRITE +std::string CBodyGeneratorBase::GenListParcelWrite( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + code = std::string(CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_WRITE); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_LIST_BUNDLE_PARCEL_WRITE); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = std::string(CB_STRUCTURE_LIST_STRING_PARCEL_WRITE); } else { - str += GenTemplateString(CB_IF_STATEMENT, - [&]()->std::string { - return handle + id; - }, - [&]()->std::string { - return GetDestructorString(type, handle + id) + NLine(1); - }); + code = ReplaceAll(CB_STRUCTURE_LIST_BASE_PARCEL_WRITE, "", + GetParcelType(type)); } - return str; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetSetterString(const std::string& id, - const BaseType& type) { - std::string str; - +// @see #CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_READ +// @see #CB_STRUCTURE_LIST_BUNDLE_PARCEL_READ +// @see #CB_STRUCTURE_LIST_STRING_PARCEL_READ +// @see #CB_STRUCTURE_LIST_BASE_PARCEL_READ +std::string CBodyGeneratorBase::GenListParcelRead( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); if (type.IsUserDefinedType() || - type.ToString() == "string" || - type.ToString() == "bundle" || - type.ToString() == "file") { - str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - std::string s; - s += GetDestructorString(type, "h->" + id) + NLine(1); - s += GetSetterString("h->" + id, "NULL"); - return s; - }); - str += NLine(1); - - str += NLine(1); - str += GetSetterString(type, "h->" + id, id); - str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!h->" + id; - }, - [&]()->std::string { - std::string s; - s += "_E(\"Failed to duplicate data\");" + NLine(1); - s += "return -1;"; - return s; - }); - str += NLine(1); - } else if (type.ToString() == "list") { - str += GenTemplateString(CB_SETTER_LIST_BLOCK, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - std::string s; - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "string" || - type.GetMetaType()->ToString() == "bundle" || - type.GetMetaType()->ToString() == "file" || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") { - s += GetSetterString(*type.GetMetaType(), "value", id); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!value"; - }, - [&]()->std::string { - std::string s; - s += "_E(\"Out of memory\");" + NLine(1); - s += "return -1;"; - return s; - }); - s += NLine(1); - } else { - s += "value = calloc(1, sizeof(*value));" + NLine(1); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!value"; - }, - [&]()->std::string { - std::string s; - s += "_E(\"Out of memory\");" + NLine(1); - s += "return -1;"; - return s; - }); - s += NLine(1); - s += GetSetterString("*value", id); - } - return s; - }, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - return "h->" + id; - }); - } else if (type.ToString() == "array") { - str += GetFinalizeString(id, type, "h->") + NLine(1); - str += GetSetterString("h->" + id, "NULL"); - str += NLine(1); - str += GenTemplateString(ReplaceAll(CB_SETTER_ARRAY_BLOCK, "##", id), - [&]()->std::string { - std::string s; - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") - s += "int __ret = "; - - s += GetSetterString(*type.GetMetaType(), "h->" + id + "[i]", - id + "[i]"); - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") { - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "__ret != 0"; - }, - [&]()->std::string { - std::string r; - r += "_E(\"Failed to clone " + id + "\");" + NLine(1); - r += GetFinalizeString(id, type, "h->") + NLine(1); - r += GetSetterString("h->" + id, "NULL") + NLine(1); - r += "return -1;"; - return r; - }); - } - - s += NLine(1); - return s; - }); + type.ToString() == "list" || + type.ToString() == "array") { + code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + + std::string name; + auto* meta_type = type.GetMetaType(); + if (meta_type == nullptr) + name = type.ToString(); + else + name = GetFullNameFromType(*meta_type); + + code = ReplaceAll(code, "", name); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_LIST_BUNDLE_PARCEL_READ); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = std::string(CB_STRUCTURE_LIST_STRING_PARCEL_READ); } else { - str += GetSetterString(type, "h->" + id, id); + auto value_type = GetParamTypeString(ParameterType::Direction::IN, type); + value_type = RemoveLastSpaces(value_type); + code = ReplaceAll(CB_STRUCTURE_LIST_BASE_PARCEL_READ, "", + value_type); + code = ReplaceAll(code, "", GetParcelType(type)); } - return str; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetGetterString(const std::string& id, - const BaseType& type) { - std::string str; - - if (type.ToString() == "array") { - str += GenTemplateString(ReplaceAll(CB_GETTER_ARRAY_BLOCK, "##", id), - [&]()->std::string { - std::string s; - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") - s += "int __ret = "; - - s += GetSetterString(*type.GetMetaType(), - "(*" + id + ")[i]", "h->" + id + "[i]"); - - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") { - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "__ret != 0"; - }, - [&]()->std::string { - std::string r; - r += "_E(\"Failed to clone " + id + "\");" + NLine(1); - r += GetFinalizeString("*" + id, type, "") + NLine(1); - r += GetSetterString("*" + id, "NULL") + NLine(1); - r += "return -1;"; - return r; - }); - } - - s += NLine(1); - return s; - }); - } else { - if (type.IsUserDefinedType() || - type.ToString() == "string" || - type.ToString() == "bundle" || - type.ToString() == "file") { - str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!h->" + id; - }, - [&]()->std::string { - std::string s; - s += "_E(\"Invalid parameter: h->" + id + " is NULL\");" + NLine(1); - s += "return -1;"; - return s; - }); - str += NLine(1); - str += NLine(1); - } +// @see #CB_STRUCTURE_LIST_USER_DEFINED_ADD +// @see #CB_STRUCTURE_LIST_BUNDLE_ADD +// @see #CB_STRUCTURE_LIST_STRING_ADD +// @see #CB_STRUCTURE_LIST_BASE_ADD +std::string CBodyGeneratorBase::GenListAdd( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + code = ReplaceAll(CB_STRUCTURE_LIST_USER_DEFINED_ADD, "", + GetHandlePrefix()); - if (type.IsUserDefinedType()) { - str += GetHandlePrefix() + GetFullNameFromType(type) + - "_clone(h->"+ id + ", " + id +");" + NLine(1); - } else { - str += GetSetterString(type, "*" + id, "h->" + id); - } + std::string name; + auto* meta_type = type.GetMetaType(); + if (meta_type == nullptr) + name = type.ToString(); + else + name = GetFullNameFromType(*meta_type); - if (type.IsUserDefinedType() || - type.ToString() == "string" || - type.ToString() == "bundle" || - type.ToString() == "file") { - str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "*" + id + " == NULL"; - }, - [&]()->std::string { - std::string s; - s += "_E(\"Failed to duplicate " + id + "\");" + NLine(1); - s += "return -1;"; - return s; - }); - str += NLine(1); - } + code = ReplaceAll(code, "", name); + } else if (type.ToString() == "bundle") { + code = std::string(CB_STRUCTURE_LIST_BUNDLE_ADD); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = std::string(CB_STRUCTURE_LIST_STRING_ADD); + } else { + auto value_type = GetParamTypeString(ParameterType::Direction::IN, type); + code = ReplaceAll(CB_STRUCTURE_LIST_BASE_ADD, "", + value_type); } - return str; -} -std::string CBodyGeneratorBase::GetIteratorString(const std::string& id, - const BaseType& type) { - std::string str; - - str += GenTemplateString(CB_ITERATOR_BLOCK, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array" || - type.GetMetaType()->ToString() == "string" || - type.GetMetaType()->ToString() == "bundle" || - type.GetMetaType()->ToString() == "file") - return "value"; - - return "*value"; - }); - - return str; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetClonerString(const std::string& id, - const BaseType& type, - const Structure& st) { - std::string str; - +std::string CBodyGeneratorBase::GenListCallbackParamType( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); if (type.IsUserDefinedType() || - type.ToString() == "string" || + type.ToString() == "list" || + type.ToString() == "array"|| type.ToString() == "bundle" || - type.ToString() == "file") { - str += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - std::string s; - s += GetSetterString(type, "handle->" + id, "h->" + id); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!handle->" + id; - }, - [&]()->std::string { - std::string ss; - ss += "_E(\"Failed to duplicate h->" + id + "\");" + NLine(1); - ss += "rpc_port_" + GetStructIdWithNamespace(st) - + "_destroy(handle);" + NLine(1); - ss += "return -1;"; - return ss; - }); - return s; - }); - str += NLine(1); - } else if (type.ToString() == "list") { - str += GenTemplateString(CB_CLONER_LIST_BLOCK, - [&]()->std::string { - return "h->" + id; - }, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - return GetParcelParamTypeString(*type.GetMetaType()); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - std::string s; - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array" || - type.GetMetaType()->ToString() == "string" || - type.GetMetaType()->ToString() == "bundle" || - type.GetMetaType()->ToString() == "file") { - s += GetSetterString(*type.GetMetaType(), - "new_value", "value"); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!new_value"; - }, - [&]()->std::string { - std::string ss; - ss += "_E(\"Failed to duplicate value\");" + NLine(1); - ss += "rpc_port_" + GetStructIdWithNamespace(st) - + "_destroy(handle);" + NLine(1); - ss += "return -1;"; - return ss; - }); - } else { - s += "new_value = calloc(1, sizeof(*new_value));" + NLine(1); - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "!new_value"; - }, - [&]()->std::string { - std::string tmp; - tmp += "_E(\"Out of memory\");" + NLine(1); - tmp += "rpc_port_" + GetStructIdWithNamespace(st) - + "_destroy(handle);" + NLine(1); - tmp += "return -1;"; - return tmp; - }); - s += NLine(1); - s += GetSetterString(*type.GetMetaType(), - "*new_value", "*value"); - } - s += NLine(1); - return s; - }, - [&]()->std::string { - return "handle->" + id; - }, - [&]()->std::string { - return "handle->" + id; - }); - } else if (type.ToString() == "array") { - str += GenTemplateString(ReplaceAll(CB_CLONER_ARRAY_BLOCK, "##", id), - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - std::string s; - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") - s += "int __ret = "; - - s += GetSetterString(*type.GetMetaType(), - "handle->" + id + "[i]", "h->" + id + "[i]"); - - if (type.GetMetaType()->IsUserDefinedType() || - type.GetMetaType()->ToString() == "list" || - type.GetMetaType()->ToString() == "array") { - s += GenTemplateString(CB_IF_STATEMENT_WITH_BRACES, - [&]()->std::string { - return "__ret != 0"; - }, - [&]()->std::string { - std::string tmp; - tmp += "_E(\"Failed to clone " + id + "\");" + NLine(1); - tmp += "rpc_port_" + GetStructIdWithNamespace(st) + - "_destroy(handle);" + NLine(1); - tmp += "return -1;"; - return tmp; - }); - } - - s += NLine(1); - return s; - }); - } else { - str += GetSetterString(type, "handle->" + id, "h->" + id); - } + type.ToString() == "string" || + type.ToString() == "file") + code = std::string("value"); + else + code = std::string ("*value"); + + return code; +} + +// @see #CB_STRUCTURE_LIST_BASE +void CBodyGeneratorBase::GenStructureListBase(std::ofstream& stream, + const Structure& st) { + std::string code = ReplaceAll(CB_STRUCTURE_LIST_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", st.GetID()); + + auto& elm = st.GetElements().GetElms().front(); + auto& type = elm->GetType(); + code = ReplaceAll(code, "", GetDataTypeString(type, true)); + code = ReplaceAll(code, "", GenListDataFree(elm)); - return str; + auto param_type = GetParamTypeString(ParameterType::Direction::IN, type); + code = ReplaceAll(code, "", param_type); + + code = ReplaceAll(code, "", GenListParcelWrite(elm)); + code = ReplaceAll(code, "", GenListParcelRead(elm)); + + code = ReplaceAll(code, "", GenListAdd(elm)); + code = ReplaceAll(code, "", + GenListCallbackParamType(elm)); + + stream << SmartIndent(code); } -std::string CBodyGeneratorBase::GetDestructorString(const BaseType& type, - const std::string& value, - bool container_value) { - std::string str; +std::string CBodyGeneratorBase::GenBaseElements(const Elements& elms) { + std::string code; + for (auto& elm : elms.GetElms()) { + auto& type = elm->GetType(); + auto param_type = GetDataTypeString(type, false); + code += param_type + elm->GetID() + ";"; + code += NLine(1); + } + + return code; +} +// @see #CB_STRUCTURE_BASE_USER_DEFINED_FREE +// @see #CB_STRUCTURE_BASE_BUNDLE_FREE +// @see #CB_STRUCTURE_BASE_STRING_FREE +std::string CBodyGeneratorBase::GenBaseElementFree( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); if (type.IsUserDefinedType() || type.ToString() == "list" || type.ToString() == "array") { - str += GetHandlePrefix() + GetFullNameFromType(type) + - "_destroy(" + value + ");"; + code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_FREE, "", + GetHandlePrefix()); + + std::string name = GetFullNameFromType(type); + code = ReplaceAll(code, "", name); + code = ReplaceAll(code, "", elm->GetID()); } else if (type.ToString() == "bundle") { - str += "bundle_free(" + value + ");"; - } else if (type.ToString() == "string" || type.ToString() == "file" || container_value) { - str += "free(" + value + ");"; + code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_FREE, "", + elm->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "flie") { + code = ReplaceAll(CB_STRUCTURE_BASE_STRING_FREE, "", + elm->GetID()); } - return str; + return code; +} + +std::string CBodyGeneratorBase::GenBaseElementsFree(const Elements& elms) { + std::string code; + for (auto& elm : elms.GetElms()) + code += GenBaseElementFree(elm); + + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetConstructorString(const BaseType& type, - const std::string& value) { - std::string str; - str += GetHandlePrefix() + GetFullNameFromType(type) + - "_create(&" + value + ");" + NLine(1); - return str; +// @see #CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_WRITE +// @see #CB_STRUCTURE_BASE_BUNDLE_PARCEL_WRITE +// @see #CB_STRUCTURE_BASE_STRING_PARCEL_WRITE +// @see #CB_STRUCTURE_BASE_BASE_PARCEL_WRITE +std::string CBodyGeneratorBase::GenBaseParcelWrite(const Elements& elms) { + std::string code; + for (auto& elm : elms.GetElms()) { + std::string parcel_write_code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll( + CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_WRITE, "", + elm->GetID()); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_PARCEL_WRITE, + "", elm->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_STRUCTURE_BASE_STRING_PARCEL_WRITE, + "", elm->GetID()); + } else { + parcel_write_code = ReplaceAll(CB_STRUCTURE_BASE_BASE_PARCEL_WRITE, + "", GetParcelType(type)); + parcel_write_code = ReplaceAll(parcel_write_code, "", + elm->GetID()); + } + + code += parcel_write_code; + } + + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetSetterString(const BaseType& type, - const std::string& lvalue, - const std::string& rvalue) { - std::string str; +// @see #CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_READ +// @see #CB_STRUCTURE_BASE_BUNDLE_PARCEL_READ +// @see #CB_STRUCTURE_BASE_STRING_PARCEL_READ +// @see #CB_STRUCTURE_BASE_BASE_PARCEL_READ +std::string CBodyGeneratorBase::GenBaseParcelRead(const Elements& elms) { + std::string code; + for (auto& elm : elms.GetElms()) { + std::string parcel_read_code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_read_code = ReplaceAll( + CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + parcel_read_code = ReplaceAll(parcel_read_code, "", + GetFullNameFromType(type)); + parcel_read_code = ReplaceAll(parcel_read_code, "", + elm->GetID()); + } else if (type.ToString() == "bundle") { + parcel_read_code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_PARCEL_READ, + "", elm->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + parcel_read_code = ReplaceAll(CB_STRUCTURE_BASE_STRING_PARCEL_READ, + "", elm->GetID()); + } else { + parcel_read_code = ReplaceAll(CB_STRUCTURE_BASE_BASE_PARCEL_READ, + "", GetParcelType(type)); + parcel_read_code = ReplaceAll(parcel_read_code, "", + elm->GetID()); + } + + code += parcel_read_code; + } + + return RemoveLine(code); +} +// @see #CB_STRUCTURE_BASE_USER_DEFINED_SET +// @see #CB_STRUCTURE_BASE_BUNDLE_SET +// @see #CB_STRUCTURE_BASE_STRING_SET +// @see #CB_STRUCTURE_BASE_BASE_SET +std::string CBodyGeneratorBase::GenBaseSet( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); if (type.IsUserDefinedType() || type.ToString() == "list" || type.ToString() == "array") { - str += GetHandlePrefix() + GetFullNameFromType(type) + - "_clone(" + rvalue + ", &" + lvalue +");" + NLine(1); - } else if (type.ToString() == "string" || type.ToString() == "file") { - str += lvalue + " = strdup(" + rvalue + ");" + NLine(1); + code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_SET, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", GetFullNameFromType(type)); + + auto element_free_code = RemoveLine(GenBaseElementFree(elm)); + code = ReplaceAll(code, "", element_free_code); + code = ReplaceAll(code, "", elm->GetID()); } else if (type.ToString() == "bundle") { - str += lvalue + " = bundle_dup(" + rvalue + ");" + NLine(1); + auto element_free_code = RemoveLine(GenBaseElementFree(elm)); + code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_SET, "", + element_free_code); + code = ReplaceAll(code, "", elm->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + auto element_free_code = RemoveLine(GenBaseElementFree(elm)); + code = ReplaceAll(CB_STRUCTURE_BASE_STRING_SET, "", + element_free_code); + code = ReplaceAll(code, "", elm->GetID()); } else { - str += GetSetterString(lvalue, rvalue); + code = ReplaceAll(CB_STRUCTURE_BASE_BASE_SET, "", + elm->GetID()); } - return str; + return RemoveLine(code); } -std::string CBodyGeneratorBase::GetSetterString(const std::string& lvalue, - const std::string& rvalue) { - std::string str; - str += lvalue + " = " + rvalue + ";"; - return str; +// @see #CB_STRUCTURE_BASE_USER_DEFINED_GET +// @see #CB_STRUCTURE_BASE_BUNDLE_GET +// @see #CB_STRUCTURE_BASE_STRING_GET +// @see #CB_STRUCTURE_BASE_BASE_GET +std::string CBodyGeneratorBase::GenBaseGet( + const std::unique_ptr& elm) { + std::string code; + auto& type = elm->GetType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + code = ReplaceAll(CB_STRUCTURE_BASE_USER_DEFINED_GET, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", GetFullNameFromType(type)); + code = ReplaceAll(code, "", elm->GetID()); + } else if (type.ToString() == "bundle") { + code = ReplaceAll(CB_STRUCTURE_BASE_BUNDLE_GET, "", + elm->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + code = ReplaceAll(CB_STRUCTURE_BASE_STRING_GET, "", + elm->GetID()); + } else { + code = ReplaceAll(CB_STRUCTURE_BASE_BASE_GET, "", + elm->GetID()); + } + + return RemoveLine(code); } -void CBodyGeneratorBase::GenIncludeHeader(std::ofstream& stream) { - std::string str; - str += "#include \""; - str += FileName.substr(0, FileName.length() - 2); - str += ".h\""; - stream << NLine(1); - stream << str; - stream << NLine(1); +// @see #CB_STRUCTURE_BASE_SET_GET +std::string CBodyGeneratorBase::GenBaseSetGet(const std::string& name, + const Elements& elms) { + std::string code; + for (auto& elm : elms.GetElms()) { + std::string set_get_code = ReplaceAll(CB_STRUCTURE_BASE_SET_GET, + "", GetHandlePrefix()); + set_get_code = ReplaceAll(set_get_code, "", name); + set_get_code = ReplaceAll(set_get_code, "", elm->GetID()); + + auto& type = elm->GetType(); + auto param_type_in = GetParamTypeString(ParameterType::Direction::IN, type); + set_get_code = ReplaceAll(set_get_code, "", param_type_in); + auto param_type_out = GetParamTypeString(ParameterType::Direction::OUT, + type); + set_get_code = ReplaceAll(set_get_code, "", param_type_out); + + set_get_code = ReplaceAll(set_get_code, "", GenBaseSet(elm)); + set_get_code = ReplaceAll(set_get_code, "", GenBaseGet(elm)); + + code += set_get_code; + } + + return RemoveLine(code); } -void CBodyGeneratorBase::GenLogTag(std::ofstream& stream, - const std::string& log_tag) { - GenTemplate(CB_LOG_TAG, stream, - [&]()->std::string { - return log_tag; - }); +// @see #CB_STRUCTURE_BASE +void CBodyGeneratorBase::GenStructureBase(std::ofstream& stream, + const Structure& st) { + std::string code = ReplaceAll(CB_STRUCTURE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", st.GetID()); + + auto& elms = st.GetElements(); + code = ReplaceAll(code, "", GenBaseElementsFree(elms)); + + code = ReplaceAll(code, "", GenBaseParcelWrite(elms)); + code = ReplaceAll(code, "", GenBaseParcelRead(elms)); + + code += GenBaseSetGet(st.GetID(), elms); + + stream << SmartIndent(code); } -void CBodyGeneratorBase::GenInterfaceEnumerations(std::ofstream& stream, - const Interface& inf) { - GenInterfaceMethodEnumeration(stream, inf); - GenInterfaceDelegateEnumeration(stream, inf); +const std::string& CBodyGeneratorBase::GetParcelType(const BaseType& type) { + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") + return parcel_type_map_["none"]; + + return parcel_type_map_[type.ToString()]; } -bool CBodyGeneratorBase::HasDelegate(const Interface& inf) const { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) { - return true; +bool CBodyGeneratorBase::HasListFile(const Interface& inf) { + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (IsProxy() && d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + for (auto& p : d->GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + auto name = GetFullNameFromType(type, inf); + if (name == "list_file") + return true; } } return false; } -void CBodyGeneratorBase::GenInterfaceDelegateEnumeration( - std::ofstream& stream, const Interface& inf) { - int count = 1; +// @see #CB_PRIVATE_SHARING_LIST_SET +void CBodyGeneratorBase::GenPrivateSharingListSet(std::ofstream& stream) { + bool has_list_file = false; + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; - if (!HasDelegate(inf)) - return; + auto& inf = static_cast(*i); + has_list_file = HasListFile(inf); + if (has_list_file) + break; + } - stream << SmartIndent(GenTemplateString(CB_DELEGATE_ENUM, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - std::string str; - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) - continue; - - str += GenTemplateString(CB_DELEGATE_ENUM_FORMAT, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return std::to_string(count++); - }); - } - return str; - })); -} + if (!has_list_file) + return; -void CBodyGeneratorBase::GenInterfaceMethodEnumeration( - std::ofstream& stream, const Interface& inf) { - stream << SmartIndent(GenTemplateString(CB_METHOD_ENUM, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - std::string str; - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) - continue; - str += GenTemplateString(CB_METHOD_ENUM_FORMAT, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return i->GetID(); - }); - } - return str; - })); -} + stream << SmartIndent(std::string(CB_PRIVATE_SHARING_LIST_SET)); +} + +// @see #CB_LIST_FILE_SET_PRIVATE_SHARING +// @see #CB_ARRAY_FILE_SET_PRIVATE_SHARING +// @see #CB_FILE_SET_PRIVATE_SHARING +std::string CBodyGeneratorBase::GetPrivateSharingString(const BaseType& type, + const Interface& inf, const std::string& port, const std::string& arg) { + std::string code; + std::string name = GetFullNameFromType(type, inf); + if (name == "list_file") { + code = ReplaceAll(CB_LIST_FILE_SET_PRIVATE_SHARING, "", port); + code = ReplaceAll(code, "", arg); + } else if (name == "array_file") { + code = ReplaceAll(CB_ARRAY_FILE_SET_PRIVATE_SHARING, "", port); + code = ReplaceAll(code, "", arg); + } else if (name == "file") { + code = ReplaceAll(CB_FILE_SET_PRIVATE_SHARING, "", port); + code = ReplaceAll(code, "", arg); + } -void CBodyGeneratorBase::GenLogDefinition(std::ofstream& stream) { - stream << SmartIndent(CB_LOG_DEF); + return code; } } // namespace tidl diff --git a/idlc/gen/c_body_gen_base.h b/idlc/gen/c_body_gen_base.h index 7de82463..03c7476e 100644 --- a/idlc/gen/c_body_gen_base.h +++ b/idlc/gen/c_body_gen_base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,58 +30,49 @@ class CBodyGeneratorBase : public CGeneratorBase { explicit CBodyGeneratorBase(std::shared_ptr doc); virtual ~CBodyGeneratorBase() = default; + void GenStructureDefs(std::ofstream& stream); void GenStructures(std::ofstream& stream); void GenIncludeHeader(std::ofstream& stream); void GenLogTag(std::ofstream& stream, const std::string& log_tag); - void GenInterfaceEnumerations(std::ofstream& stream, const Interface& inf); - std::string GetParcelWriteFunctionString(const BaseType& type, - bool meta_type = false); - std::string GetParcelReadFunctionString(const BaseType& type, - bool meta_type = false); - std::string GetDestructorString(const BaseType& type, - const std::string& value, - bool container_value = false); - std::string GetConstructorString(const BaseType& type, - const std::string& value); - bool HasDelegate(const Interface& inf) const; void GenLogDefinition(std::ofstream& stream); + void GenBaseDefinition(std::ofstream& stream); + const std::string& GetParcelType(const BaseType& type); - private: - void GenInterfaceMethodEnumeration(std::ofstream& stream, - const Interface& inf); - void GenInterfaceDelegateEnumeration(std::ofstream& stream, - const Interface& inf); + void GenPrivateSharingListSet(std::ofstream& stream); + std::string GetPrivateSharingString(const BaseType& type, + const Interface& inf, const std::string& port, const std::string& arg); private: + void GenStructureDef(std::ofstream& stream, const Structure& st); + void GenStructureBaseDef(std::ofstream& stream, const Structure& st); + void GenStructureArrayDef(std::ofstream& stream, const Structure& st); + void GenStructureListDef(std::ofstream& stream, const Structure& st); + void GenStructure(std::ofstream& stream, const Structure& st); - void GenStructureDeclaration(std::ofstream& stream, const Structure& st); - void GenStructureParcelSerializer(std::ofstream& stream, const Structure& st); - void GenStructureParcelDeserializer(std::ofstream& stream, - const Structure& st); - void GenStructureConstructor(std::ofstream& stream, const Structure& st); - void GenStructureDestructor(std::ofstream& stream, const Structure& st); - void GenStructureSetter(std::ofstream& stream, const Structure& st); - void GenStructureGetter(std::ofstream& stream, const Structure& st); - void GenStructureIterator(std::ofstream& stream, const Structure& st); - void GenStructureCloner(std::ofstream& stream, const Structure& st); - void GenStructureRemover(std::ofstream& stream, const Structure& st); - void GenStructureLengthGetter(std::ofstream& stream, const Structure& st); + void GenStructureBase(std::ofstream& stream, const Structure& st); + void GenStructureArrayBase(std::ofstream& stream, const Structure& st); + void GenStructureListBase(std::ofstream& stream, const Structure& st); - private: - std::string GetParcelTypeString(const BaseType& type, bool meta_type); - std::string GetParcelWriteString(const std::string& id, const BaseType& type); - std::string GetParcelReadString(const std::string& id, const BaseType& type); - std::string GetFinalizeString(const std::string& id, const BaseType& type, - const std::string& handle); - std::string GetSetterString(const std::string& id, const BaseType& type); - std::string GetGetterString(const std::string& id, const BaseType& type); - std::string GetIteratorString(const std::string& id, const BaseType& type); - std::string GetClonerString(const std::string& id, const BaseType& type, - const Structure& st); - std::string GetSetterString(const BaseType& type, const std::string& lvalue, - const std::string& rvalue); - std::string GetSetterString(const std::string& lvalue, - const std::string& rvalue); + std::string GenArrayParcelWrite(const std::unique_ptr& elm); + std::string GenArrayParcelRead(const std::unique_ptr& elm); + std::string GenArrayElementsFree(const std::unique_ptr& elm); + + std::string GenListDataFree(const std::unique_ptr& elm); + std::string GenListParcelWrite(const std::unique_ptr& elm); + std::string GenListParcelRead(const std::unique_ptr& elm); + std::string GenListAdd(const std::unique_ptr& elm); + std::string GenListCallbackParamType(const std::unique_ptr& elm); + + std::string GenBaseElements(const Elements& elms); + std::string GenBaseElementFree(const std::unique_ptr& elm); + std::string GenBaseElementsFree(const Elements& elms); + std::string GenBaseParcelWrite(const Elements& elms); + std::string GenBaseParcelRead(const Elements& elms); + std::string GenBaseSetGet(const std::string& name, const Elements& elms); + std::string GenBaseSet(const std::unique_ptr& elm); + std::string GenBaseGet(const std::unique_ptr& elm); + + bool HasListFile(const Interface& inf); private: std::map parcel_type_map_; diff --git a/idlc/gen/c_body_gen_base_cb.h b/idlc/gen/c_body_gen_base_cb.h index e9bcc76c..a8f9a67b 100644 --- a/idlc/gen/c_body_gen_base_cb.h +++ b/idlc/gen/c_body_gen_base_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,457 +17,575 @@ #ifndef IDLC_C_GEN_C_BODY_GEN_BASE_CB_H_ #define IDLC_C_GEN_C_BODY_GEN_BASE_CB_H_ -const char CB_STRUCT_DECL[] = +/** + * The log tag. + */ +constexpr const char CB_LOG_TAG[] = R"__c_cb( -$$struct $$_s { - rpc_port_parcelable_t parcelable;$$ -}; +#undef LOG_TAG +#define LOG_TAG "" )__c_cb"; -const char CB_STRUCT_SERIALIZER[] = +constexpr const char CB_LOG_DEF[] = R"__c_cb( -static void __##_to(rpc_port_parcel_h parcel, void *data) -{ - rpc_port_##_h h = data; +#undef _E +#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) - if (!parcel || !h) { - _E("Invalid parameter"); - return; - } -$$ -} +#undef _W +#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#undef _I +#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#undef _D +#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) )__c_cb"; -const char CB_STRUCT_DESERIALIZER[] = +constexpr const char CB_BASE_DEF[] = R"__c_cb( -static void __##_from(rpc_port_parcel_h parcel, void *data) -{ - rpc_port_##_h h = data; +#ifndef nullptr +#define nullptr NULL +#endif - if (!parcel || !h) { - _E("Invalid parameter"); - return; - } -$$ -} +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + +#ifndef STRING_GET +#define STRING_GET(x) ((x) ? x : "") +#endif )__c_cb"; -const char CB_STRUCT_CTOR[] = +/** + * The prefix of the structure. + * The name of the structure. + * Elements of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_DEF[] = +R"__c_cb( +typedef struct __s { + rpc_port_parcelable_t parcelable; + +} __t; +)__c_cb"; + +/** + * The prefix of the structure. + * The name of the structure. + * The implementation to release elements of the structure. + * The implementation to write the data to the parcel. + * The implementation to read the data from the parcel. + */ +constexpr const char CB_STRUCTURE_BASE[] = R"__c_cb( -int rpc_port_##_create(rpc_port_##_h *h) +static void ____to(rpc_port_parcel_h parcel, void *data) { - struct ##_s *handle; + __h h = data; - if (!h) { - _E("Invalid parameter"); - return -1; - } + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + return; + } - handle = calloc(1, sizeof(struct ##_s)); - if (!handle) { - _E("Out of memory"); - return -1; - } + +} + +static void ____from(rpc_port_parcel_h parcel, void *data) +{ + __h h = data; - handle->parcelable.to = __##_to; - handle->parcelable.from = __##_from; + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } - *h = handle; + - return 0; + set_last_result(RPC_PORT_ERROR_NONE); } -)__c_cb"; -const char CB_STRUCT_DTOR[] = -R"__c_cb( -int rpc_port_##_destroy(rpc_port_##_h h) +int __create(__h *h) { - if (!h) { - _E("Invalid parameter"); - return -1; - } + __t *handle; -$$ - free(h); + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - return 0; + handle = calloc(1, sizeof(__t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + handle->parcelable.to = ____to; + handle->parcelable.from = ____from; + + *h = handle; + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_STRUCT_SETTER[] = -R"__c_cb( -int rpc_port_$$_$$_$$(rpc_port_$$_h h, $$$$) +int __destroy(__h h) { - if ($$) { - _E("Invalid parameter"); - return -1; - } -$$ - return 0; + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + + + free(h); + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_STRUCT_GETTER[] = -R"__c_cb( -int rpc_port_$$_get_$$(rpc_port_$$_h h, $$$$) +int __clone(__h h, __h *clone) { - if (!h || $$) { - _E("Invalid parameter"); - return -1; - } -$$ - return 0; + __h handle; + rpc_port_parcel_h parcel; + int ret; + + if (h == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret = __create(&handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + return ret; + } + + ret = rpc_port_parcel_create(&parcel); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret); + __destroy(handle); + return ret; + } + + rpc_port_parcel_write(parcel, &h->parcelable, h); + rpc_port_parcel_read(parcel, &handle->parcelable, handle); + ret = get_last_result(); + rpc_port_parcel_destroy(parcel); + + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", ret); + __destroy(handle); + return ret; + } + + *clone = handle; + + return RPC_PORT_ERROR_NONE; } )__c_cb"; -const char CB_STRUCT_ITERATOR[] = +/** + * The prefix of the structure. + * The name of the structure. + * The type of the input paramter. + * The type of the output parameter. + * The name of the element of the structure. + * The implementation to set the data to the structure. + * The implementation to get the data from the structure. + */ +constexpr const char CB_STRUCTURE_BASE_SET_GET[] = R"__c_cb( -int rpc_port_$$_foreach_$$(rpc_port_$$_h h, - bool (*callback)($$$$, void *user_data), void *user_data) +int __set_(__h h, value) { - if (!h || !callback) { - _E("Invalid parameter"); - return -1; - } -$$ - return 0; + } -)__c_cb"; -const char CB_STRUCT_REMOVER[] = -R"__c_cb( -int rpc_port_$$_remove_$$(rpc_port_$$_h h, unsigned int nth) +int __get_(__h h, value) { - GList *iter; + +} +)__c_cb"; - if (!h) { - _E("Invalid parameter"); - return -1; - } +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write(parcel, &h->->parcelable, h->); +)__c_cb"; - iter = g_list_nth(h->$$, nth); - if (iter == NULL) - return -1; +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BUNDLE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_bundle(parcel, h->); +)__c_cb"; - $$value = iter->data; - h->$$ = g_list_remove_link(h->$$, iter); -$$ - g_list_free(iter); +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel, STRING_GET(h->)); +)__c_cb"; - return 0; -} +/** + * The type of the parcel of the element. + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BASE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_(parcel, h->); )__c_cb"; -const char CB_STRUCT_LENGTH_GETTER[] = +/** + * The prefix of the element type. + * The name of the element type. + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_PARCEL_READ[] = R"__c_cb( -int rpc_port_$$_get_$$_length(rpc_port_$$_h h, unsigned int *length) -{ - if (!h || !length) { - _E("Invalid parameter"); - return -1; - } +__create(&h->); +if (h-> == nullptr) { + _E("Failed to create handle"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; +} - *length = g_list_length(h->$$); +rpc_port_parcel_read(parcel, &h->->parcelable, h->); +if (get_last_result() != RPC_PORT_ERROR_NONE) { + _E("Failed to read data"); + return; +} +)__c_cb"; - return 0; +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BUNDLE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_bundle(parcel, &h->); +if (h-> == nullptr) { + _E("Failed to read data"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; } )__c_cb"; -const char CB_STRUCT_CLONER[] = +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_STRING_PARCEL_READ[] = R"__c_cb( -int rpc_port_##_clone(rpc_port_##_h h, rpc_port_##_h *clone) -{ - rpc_port_##_h handle = NULL; - - if (!h || !clone) { - _E("Invalid parameter"); - return -1; - } - - rpc_port_##_create(&handle); - if (!handle) { - _E("Failed to create ## handle"); - return -1; - } -$$ - *clone = handle; - - return 0; +rpc_port_parcel_read_string(parcel, &h->); +if (h-> == nullptr) { + _E("Failed to read data"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; } )__c_cb"; -const char CB_WRITE_LIST_BLOCK[] = +/** + * The type of the parcel of the element. + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BASE_PARCEL_READ[] = R"__c_cb( -do { - GList *iter; +rpc_port_parcel_read_(parcel, &h->); +)__c_cb"; - iter = $$; - while (iter) { - $$value = iter->data; +/** + * The name of the element of the structure. + * The prefix of the element type. + * The name of the element type. + */ +constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_FREE[] = +R"__c_cb( +if (h->) + __destroy(h->); +)__c_cb"; - iter = g_list_next(iter); - if (!value) { - _W("Warning: value is NULL"); - continue; - } - $$ - } -} while (0); +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BUNDLE_FREE[] = +R"__c_cb( +if (h->) + bundle_free(h->); )__c_cb"; -const char CB_WRITE_ARRAY_BLOCK[] = +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_STRING_FREE[] = R"__c_cb( -do { - for (int i = 0; i < $$; i++) { -$$ - } -} while (0); +if (h->) + free(h->); )__c_cb"; -const char CB_READ_LIST_BLOCK[] = -R"__c_cb(do { - int len = 0; +/** + * The prefix of the element type. + * The name of the element type. + * The implementation to release the element of the structure. + * The name of the element of the structure. + * @see #CB_STRUCTURE_BASE_USER_DEFINED_FREE + */ +constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_SET[] = +R"__c_cb( +__h new_value; +int ret; + +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +ret = __clone(value, &new_value); +if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to clone handle. error(%d)", ret); + return ret; +} + + - $$ - for (int i = 0; i < len; i++) { - $$value = NULL; +h-> = new_value; - $$ - $$ = g_list_append($$, value); - } -} while (0); +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_READ_ARRAY_BLOCK[] = +/** + * The implementation to release the element of the structure. + * The name of the element of the structure. + * @see #CB_STRUCTURE_BASE_BUNDLE_FREE + */ +constexpr const char CB_STRUCTURE_BASE_BUNDLE_SET[] = R"__c_cb( -do { - $$ +bundle *new_value; - h->## = calloc(h->##_size, sizeof(*h->##)); - if (!h->##) { - _E("Out of memory"); - return; - } +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} - for (int i = 0; i < h->##_size; i++) { - $$value = $$; +new_value = bundle_dup(value); +if (new_value == nullptr) { + _E("Failed to duplicate value"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} - $$ - } -} while (0); -)__c_cb"; + -const char CB_READ_USER_DEFINED_BLOCK[] = -R"__c_cb(do { - rpc_port_$$_create(&h->##); - if (!h->##) { - _E("Failed to create handle"); - return; - } +h-> = new_value; - rpc_port_parcel_read(parcel, &h->##->parcelable, h->##); -} while (0); +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_FINALIZE_LIST_BLOCK[] = +/** + * The implementation to release the element of the structure. + * The name of the element of the structure. + * @see #CB_STRUCTURE_BASE_STRING_FREE + */ +constexpr const char CB_STRUCTURE_BASE_STRING_SET[] = R"__c_cb( -do { - GList *iter; - - iter = $$; - while (iter) { - $$value = iter->data; - $$ - iter = g_list_next(iter); - } - g_list_free($$); -} while (0); -)__c_cb"; +char *new_value; -const char CB_FINALIZE_ARRAY_BLOCK[] = -R"__c_cb( -do { - for (int j = 0; j < $$; j++) { - $$ - } - free($$); -} while (0); -)__c_cb"; +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} -const char CB_SETTER_LIST_BLOCK[] = -R"__c_cb( -do { - $$value = NULL; +new_value = strdup(value); +if (new_value == nullptr) { + _E("Failed to duplicate value"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} - $$ - $$ = g_list_append($$, value); -} while (0); -)__c_cb"; + -const char CB_SETTER_ARRAY_BLOCK[] = -R"__c_cb( -do { - h->## = calloc(##_size, sizeof(*##)); - if (!h->##) { - _E("Out of memory"); - return -1; - } - h->##_size = ##_size; - - for (int i = 0; i < h->##_size; i++) { - $$ - } -} while (0); +h-> = new_value; + +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_GETTER_ARRAY_BLOCK[] = +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BASE_SET[] = R"__c_cb( -do { - if (h->##_size == 0) { - _W("## is empty"); - break; - } - - *## = calloc(h->##_size, sizeof(*h->##)); - if (!*##) { - _E("Out of memory"); - return -1; - } - *##_size = h->##_size; - - for (int i = 0; i < h->##_size; i++) { - $$ - } -} while (0); +if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +h-> = value; + +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_ITERATOR_BLOCK[] = +/** + * The prefix of the element type. + * The name of the element type. + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_USER_DEFINED_GET[] = R"__c_cb( -do { - GList *iter; +__h new_value; +int ret; - iter = $$; - while (iter) { - $$value = iter->data; +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} - iter = g_list_next(iter); - if (!value) { - _W("Warning: value is NULL"); - continue; - } +if (h-> == nullptr) { + _E(" is nullptr"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} - bool ret = callback($$, user_data); - if (!ret) - break; - } -} while (0); -)__c_cb"; +ret = __clone(h->, &new_value); +if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to clone handle. error(%d)", ret); + return ret; +} -const char CB_CLONER_LIST_BLOCK[] = -R"__c_cb( -do { - GList *iter; - - iter = $$; - while (iter) { - $$new_value; - $$value = iter->data; - - if (!value) { - _E("Error: value is NULL"); - rpc_port_$$_destroy(handle); - return -1; - } +*value = new_value; - $$ - $$ = g_list_append($$, new_value); - iter = g_list_next(iter); - } -} while (0); +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_CLONER_ARRAY_BLOCK[] = +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BUNDLE_GET[] = R"__c_cb( -do { - if (h->##_size == 0) { - _W("## is empty"); - break; - } - - handle->## = calloc(h->##_size, sizeof(*h->##)); - if (!handle->##) { - _E("Out of memory"); - rpc_port_$$_destroy(handle); - return -1; - } - handle->##_size = h->##_size; - - for (int i = 0; i < h->##_size; i++) { - $$ - } -} while (0); -)__c_cb"; +bundle *new_value; -const char CB_IF_STATEMENT_WITH_BRACES[] = -R"__c_cb(if ($$) { - $$ +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; } -)__c_cb"; -const char CB_IF_STATEMENT[] = -R"__c_cb(if ($$) - $$ -)__c_cb"; +if (h-> == nullptr) { + _E(" is nullptr"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} -const char CB_DELEGATE_ENUM_FORMAT[] = "\n$$_DELEGATE_$$ = $$,"; +new_value = bundle_dup(h->); +if (new_value == nullptr) { + _E("Failed to duplicate value"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} -const char CB_DELEGATE_ENUM[] = -R"__c_cb( -enum $$_delegate_e {$$ -}; -)__c_cb"; +*value = new_value; -const char CB_METHOD_ENUM_FORMAT[] = "\n$$_METHOD_$$,"; +return RPC_PORT_ERROR_NONE; +)__c_cb"; -const char CB_METHOD_ENUM[] = +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_STRING_GET[] = R"__c_cb( -enum $$_method_e { - $$_METHOD_Result, - $$_METHOD_Callback,$$ -}; +char *new_value; + +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +if (h-> == nullptr) { + _E(" is nullptr"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +new_value = strdup(h->); +if (new_value == nullptr) { + _E("Failed to duplicate value"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} + +*value = new_value; + +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_LOG_TAG[] = +/** + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_BASE_GET[] = R"__c_cb( -#ifdef LOG_TAG -#undef LOG_TAG -#endif +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} -#define LOG_TAG "$$" +*value = h->; + +return RPC_PORT_ERROR_NONE; )__c_cb"; -const char CB_LOG_DEF[] = +constexpr const char CB_PRIVATE_SHARING_LIST_SET[] = R"__c_cb( -#ifdef _E -#undef _E -#endif +static int __rpc_port_set_private_sharing_list(rpc_port_h port, GList *list) +{ + const char **array_file; + const char *value; + guint size; + GList *iter; + int idx = 0; + int ret; + + size = g_list_length(list); + if (size == 0) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } -#ifdef _W -#undef _W -#endif + array_file = calloc(size, sizeof(const char*)); + if (array_file == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } -#ifdef _I -#undef _I -#endif + iter = list; + while (iter) { + value = iter->data; + array_file[idx++] = value; + iter = g_list_next(iter); + } -#ifdef _D -#undef _D -#endif + ret = rpc_port_set_private_sharing_array(port, array_file, idx); + free(array_file); -#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > "fmt, basename(__FILE__), __FUNCTION__, __LINE__, ##__VA_ARGS__) + return ret; +} +)__c_cb"; + +/** + * The rpc port handle. + * The argument. + */ +constexpr const char CB_LIST_FILE_SET_PRIVATE_SHARING[] = +R"__c_cb( +__rpc_port_set_private_sharing_list(, ->list); +)__c_cb"; + +/** + * The rpc port handle. + * The argument. + */ +constexpr const char CB_ARRAY_FILE_SET_PRIVATE_SHARING[] = +R"__c_cb( +rpc_port_set_private_sharing_array(, (const char **)->value, ->size); +)__c_cb"; + +/** + * The rpc port handle. + * The argument. + */ +constexpr const char CB_FILE_SET_PRIVATE_SHARING[] = +R"__c_cb( +rpc_port_set_private_sharing(, ); )__c_cb"; #endif // IDLC_C_GEN_C_BODY_GEN_BASE_CB_H_ diff --git a/idlc/gen/c_body_gen_list_base_cb.h b/idlc/gen/c_body_gen_list_base_cb.h new file mode 100644 index 00000000..d0e5ddf7 --- /dev/null +++ b/idlc/gen/c_body_gen_list_base_cb.h @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_C_GEN_C_BODY_GEN_LIST_BASE_CB_H_ +#define IDLC_C_GEN_C_BODY_GEN_LIST_BASE_CB_H_ + +/** + * The prefix of the list structure. + * The name of the list structure. + */ +constexpr const char CB_STRUCTURE_LIST_DEF[] = +R"__c_cb( +typedef struct __s { + rpc_port_parcelable_t parcelable; + GList *list; +} __t; +)__c_cb"; + +/** + * The prefix of the list structure. + * The name of the list structure. + * The type of the data of the list. + * The implementation to release the data of the list. + * The type of the parameter of the add function. + * The implementation to write the data to parcel. + * The implementation to read the data from the parcel. + * The implementation to add the data to the list. + * The type of the parameter of the callback. + */ +constexpr const char CB_STRUCTURE_LIST_BASE[] = +R"__c_cb( +static void ____to(rpc_port_parcel_h parcel, void *data) +{ + __h h = data; + value; + GList *iter; + + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + return; + } + + rpc_port_parcel_write_array_count(parcel, g_list_length(h->list)); + + iter = h->list; + while (iter) { + value = iter->data; + iter = g_list_next(iter); + + } +} + +static void ____from(rpc_port_parcel_h parcel, void *data) +{ + __h h = data; + value = nullptr; + int ret; + int len = 0; + int i; + + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + ret = rpc_port_parcel_read_array_count(parcel, &len); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read array count. error(%d)", ret); + set_last_result(ret); + return; + } + + for (i = 0; i < len; ++i) { + + } + + set_last_result(RPC_PORT_ERROR_NONE); +} + +int __create(__h *h) +{ + __t *handle; + + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + handle = calloc(1, sizeof(__t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + handle->parcelable.to = ____to; + handle->parcelable.from = ____from; + + *h = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __destroy(__h h) +{ + value; + GList *iter; + + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + if (h->list) { + iter = h->list; + while (iter) { + value = iter->data; + iter = g_list_next(iter); + + } + + g_list_free(h->list); + } + + free(h); + + return RPC_PORT_ERROR_NONE; +} + +int __clone(__h h, __h *clone) +{ + __h handle; + rpc_port_parcel_h parcel; + int ret; + + if (h == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret = __create(&handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + return ret; + } + + ret = rpc_port_parcel_create(&parcel); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret); + __destroy(handle); + return ret; + } + + rpc_port_parcel_write(parcel, &h->parcelable, h); + rpc_port_parcel_read(parcel, &handle->parcelable, handle); + ret = get_last_result(); + rpc_port_parcel_destroy(parcel); + + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", ret); + __destroy(handle); + return ret; + } + + *clone = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __add(__h h, value) +{ + +} + +int __foreach(__h h, __cb callback, void *user_data) +{ + value; + GList *iter; + + if (h == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + iter = h->list; + while (iter) { + value = iter->data; + iter = g_list_next(iter); + if (!callback(, user_data)) + break; + } + + return RPC_PORT_ERROR_NONE; +} + +int __remove(__h h, unsigned int nth) +{ + value; + GList *found; + + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + found = g_list_nth(h->list, nth); + if (found == nullptr) + return RPC_PORT_ERROR_INVALID_PARAMETER; + + value = found->data; + h->list = g_list_remove_link(h->list, found); + + g_list_free(found); + + return RPC_PORT_ERROR_NONE; +} + +int __length(__h h, unsigned int *length) +{ + if (h == nullptr || length == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *length = g_list_length(h->list); + + return RPC_PORT_ERROR_NONE; +} +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write(parcel, &value->parcelable, value); +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_BUNDLE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_bundle(parcel, value); +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel, STRING_GET(value)); +)__c_cb"; + +/** + * The type of the parcel of the value. + */ +constexpr const char CB_STRUCTURE_LIST_BASE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_(parcel, *value); +)__c_cb"; + +/** + * The prefix of the user-defined type. + * The name of the user-defined type. + */ +constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_PARCEL_READ[] = +R"__c_cb( +ret = __create(&value); +if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + set_last_result(ret); + return; +} + +rpc_port_parcel_read(parcel, &value->parcelable, value); +if (get_last_result() != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", get_last_result()); + __destroy(value); + return; +} + +h->list = g_list_append(h->list, value); +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_BUNDLE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_bundle(parcel, &value); +if (value == nullptr) { + _E("Failed to read data"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; +} + +h->list = g_list_append(h->list, value); +value = nullptr; +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_STRING_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_string(parcel, &value); +if (value == nullptr) { + _E("Failed to read data"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; +} + +h->list = g_list_append(h->list, value); +value = nullptr; +)__c_cb"; + +/** + * The type of the value. + * The type of the parcel of the value. + */ +constexpr const char CB_STRUCTURE_LIST_BASE_PARCEL_READ[] = +R"__c_cb( +value = calloc(1, sizeof(sizeof())); +if (value == nullptr) { + _E("Out of memory"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; +} + +rpc_port_parcel_read_(parcel, value); + +h->list = g_list_append(h->list, value); +)__c_cb"; + +/** + * The prefix of the user-defined type. + * The name of the user-defined type. + */ +constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_ADD[] = +R"__c_cb( +__h new_value; +int ret; + +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +ret = __clone(value, &new_value); +if (ret != RPC_PORT_ERROR_NONE) + return ret; + +h->list = g_list_append(h->list, new_value); + +return RPC_PORT_ERROR_NONE; +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_BUNDLE_ADD[] = +R"__c_cb( +bundle *new_value; + +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +new_value = bundle_dup(value); +if (new_value == nullptr) { + _E("Failed to duplicate value"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} + +h->list = g_list_append(h->list, new_value); + +return RPC_PORT_ERROR_NONE; +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_STRING_ADD[] = +R"__c_cb( +char *new_value; + +if (h == nullptr || value == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +new_value = strdup(value); +if (new_value == nullptr) { + _E("Failed to duplicate value"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} + +h->list = g_list_append(h->list, new_value); + +return RPC_PORT_ERROR_NONE; +)__c_cb"; + +/** + * The type of the value. + */ +constexpr const char CB_STRUCTURE_LIST_BASE_ADD[] = +R"__c_cb( +*new_value; + +if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; +} + +new_value = calloc(1, sizeof()); +if (new_value == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; +} + +*new_value = value; + +h->list = g_list_append(h->list, new_value); + +return RPC_PORT_ERROR_NONE; +)__c_cb"; + +/** + * The prefix of the user-defined type. + * The name of the user-defined type. + */ +constexpr const char CB_STRUCTURE_LIST_USER_DEFINED_FREE[] = +R"__c_cb( +__destroy(value); +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_BUNDLE_FREE[] = +R"__c_cb( +bundle_free(value); +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_STRING_FREE[] = +R"__c_cb( +free(value); +)__c_cb"; + +constexpr const char CB_STRUCTURE_LIST_BASE_FREE[] = +R"__c_cb( +free(value); +)__c_cb"; + +#endif // IDLC_C_GEN_C_BODY_GEN_LIST_BASE_CB_H_ diff --git a/idlc/gen/c_gen_base.cc b/idlc/gen/c_gen_base.cc index b3fe325c..f53be99f 100644 --- a/idlc/gen/c_gen_base.cc +++ b/idlc/gen/c_gen_base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,11 @@ namespace { #include "idlc/gen/c_gen_base_cb.h" -} + +constexpr const char PREFIX_RPC_PORT_PROXY[] = "rpc_port_proxy"; +constexpr const char PREFIX_RPC_PORT_STUB[] = "rpc_port_stub"; + +} // namespace namespace tidl { @@ -32,84 +36,72 @@ CGeneratorBase::CGeneratorBase(std::shared_ptr doc) : Generator(doc) { structures_.clear(); type_map_ = { - {"char", "char "}, {"int", "int "}, {"short", "short "}, - {"long", "long long "}, {"bool", "bool "}, {"string", "char *"}, - {"list", "GList *"}, {"float", "float "}, {"double", "double "}, - {"bundle", "bundle *"}, {"void", "void "}, {"file", "char *"} + {"char", "char "}, + {"int", "int "}, + {"short", "short "}, + {"long", "long long "}, + {"bool", "bool "}, + {"string", "char *"}, + {"list", "GList *"}, + {"float", "float "}, + {"double", "double "}, + {"bundle", "bundle *"}, + {"void", "void "}, + {"file", "char *"} }; } std::string CGeneratorBase::Tab(int cnt) { std::string str; - - for (int i = 0; i < cnt; ++i) { + for (int i = 0; i < cnt; ++i) str += "\t"; - } return str; } std::string CGeneratorBase::NLine(int cnt) { std::string str; - - for (int i = 0; i < cnt; ++i) { + for (int i = 0; i < cnt; ++i) str += "\n"; - } return str; } -std::string CGeneratorBase::ConvertTypeToString( - ParameterType::Direction direction, const BaseType& type, bool bconst) { - if (type.IsUserDefinedType()) { - if (direction == ParameterType::Direction::IN) - return GetHandlePrefix() + type.ToString() + "_h "; - else - return GetHandlePrefix() + type.ToString() + "_h *"; - } - - if (type.ToString() == "array") { - if (direction == ParameterType::Direction::IN) { - return GetReturnTypeString(*type.GetMetaType()) + "*"; - } else { - return GetReturnTypeString(*type.GetMetaType()) + "**"; - } - } +std::string CGeneratorBase::GetFullNameFromType(const BaseType& type) { + std::string str = type.ToString(); - if (type.ToString() == "string" || type.ToString() == "file") { - if (direction == ParameterType::Direction::IN) { - if (!bconst) - return "char *"; - return "const char *"; - } else - return "char **"; + if (type.GetMetaType() != nullptr) { + str += "_"; + str += GetFullNameFromType(*type.GetMetaType()); } - if (direction == ParameterType::Direction::IN && bconst) - return type_map_[type.ToString()]; - - return type_map_[type.ToString()] + "*"; + return str; } -std::string CGeneratorBase::GetFullNameFromType(const BaseType& type) { - std::string str = type.ToString(); +std::string CGeneratorBase::GetFullNameFromType(const BaseType& type, + const Interface& inf) { + std::string str; + if (IsDelegateType(inf, type)) + str += inf.GetID() + "_"; + + str += type.ToString(); if (type.GetMetaType() != nullptr) { str += "_"; - str += GetFullNameFromType(*type.GetMetaType()); + str += GetFullNameFromType(*type.GetMetaType(), inf); } return str; } -std::string CGeneratorBase::GetParcelParamTypeString(const BaseType& type, +std::string CGeneratorBase::GetDataTypeString(const BaseType& type, bool is_pointer) { if (type.IsUserDefinedType()) - return GetHandlePrefix() + type.ToString() + "_h "; + return GetHandlePrefix() + "_" + type.ToString() + "_h "; if (type.ToString() == "list" || type.ToString() == "array") - return GetHandlePrefix() + GetFullNameFromType(type) + "_h "; + return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h "; if (type.ToString() == "string" || type.ToString() == "file") return "char *"; @@ -125,11 +117,11 @@ std::string CGeneratorBase::GetParcelParamTypeString(const BaseType& type, std::string CGeneratorBase::GetReturnTypeString(const BaseType& type) { if (type.IsUserDefinedType()) - return GetHandlePrefix() + type.ToString() + "_h "; + return GetHandlePrefix() + "_" + type.ToString() + "_h "; if (type.ToString() == "list" || type.ToString() == "array") - return GetHandlePrefix() + GetFullNameFromType(type) + "_h "; + return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h "; return type_map_[type.ToString()]; } @@ -138,27 +130,81 @@ void CGeneratorBase::AddStructureFromType(const BaseType& type) { if (type.GetMetaType() == nullptr) return; - BaseType* t = new BaseType(type); + BaseType* t = new BaseType(*type.GetMetaType()); assert(t != nullptr); std::string type_name = GetFullNameFromType(type); - Element* elm = new Element(type_name + "s", t, "", __LINE__); + Element* elm = new Element(type_name, t, "", __LINE__); assert(elm != nullptr); Elements* elms = new Elements(); assert(elms != nullptr); elms->Add(elm); - Structure* st = new Structure(type_name, elms, "", __LINE__); + auto* st = new Structure(type_name, elms, "", __LINE__); assert(st != nullptr); - if (StructureExist(*st)) { + AddStructureFromType(*type.GetMetaType()); + + if (StructureExist(st)) { delete st; - } else { - structures_[type_name] = std::unique_ptr(st); + return; } - AddStructureFromType(*type.GetMetaType()); + structures_[type_name] = std::unique_ptr(st); +} + +void CGeneratorBase::AddStructureFromType(const BaseType& type, + const Interface& inf) { + if (type.GetMetaType() == nullptr) + return; + + BaseType* t = nullptr; + if (IsDelegateType(inf, *type.GetMetaType())) + t = new BaseType(GetFullNameFromType(*type.GetMetaType(), inf), "", true); + else + t = new BaseType(*type.GetMetaType()); + + assert(t != nullptr); + + std::string type_name = GetFullNameFromType(type, inf); + Element* elm = new Element(type_name, t, "", __LINE__); + assert(elm != nullptr); + + Elements* elms = new Elements(); + assert(elms != nullptr); + elms->Add(elm); + + auto* st = new Structure(type_name, elms, "", __LINE__); + assert(st != nullptr); + + AddStructureFromType(*type.GetMetaType(), inf); + + if (StructureExist(st)) { + delete st; + return; + } + + structures_[type_name] = std::unique_ptr(st); +} + +std::string CGeneratorBase::RemoveLine(std::string lines, + unsigned int line_num) { + std::stringstream ss(lines); + std::string result; + std::string line; + unsigned int line_count = 0; + + while (std::getline(ss, line, '\n')) { + line_count++; + if (line_num == line_count) + continue; + + result += Trim(line); + result += NLine(1); + } + + return result; } std::string CGeneratorBase::SmartIndent(std::string lines) { @@ -175,6 +221,7 @@ std::string CGeneratorBase::SmartIndent(std::string lines) { int line_count = 0; while (std::getline(ss, next_line, '\n')) { + next_line = RemoveSpaces(next_line); line_count++; if (line_count == 1) { line = Trim(next_line); @@ -187,9 +234,9 @@ std::string CGeneratorBase::SmartIndent(std::string lines) { tab_size--; } - if (line.length() > 0) { + back = line.back(); + if (back != ":" && line.length() > 0) tab += Tab(tab_size); - } if (continuous && tab_size == 0 && found == std::string::npos) { @@ -202,8 +249,7 @@ std::string CGeneratorBase::SmartIndent(std::string lines) { } continuous = false; - back = line.back(); - if (back == ",") + if (back == "," || back == "\\") continuous = true; if (line.empty() || @@ -221,7 +267,12 @@ std::string CGeneratorBase::SmartIndent(std::string lines) { result += NLine(1); } } else { - result += tab + line; + // for annotation && ifdef + if (line.compare(0, 2, " *") == 0 || line.compare(0, 1, "#") == 0) + result += line; + else + result += tab + line; + result += NLine(1); } @@ -234,6 +285,25 @@ std::string CGeneratorBase::SmartIndent(std::string lines) { tab_size++; if_statement = true; } + + found = line.find("else"); + if (found != std::string::npos && line != "#else") { + tab_size++; + if_statement = true; + } + + found = line.find("for ("); + if (found != std::string::npos) { + tab_size++; + if_statement = true; + } + + back = line.back(); + found = line.find("while ("); + if (found != std::string::npos && back != ";") { + tab_size++; + if_statement = true; + } } line = Trim(next_line); @@ -245,7 +315,35 @@ std::string CGeneratorBase::SmartIndent(std::string lines) { return result; } +std::string CGeneratorBase::RemoveLastSpaces(const std::string& str) { + std::size_t found = str.find_last_not_of(' '); + if (found == std::string::npos) + return str; + + return str.substr(0, found + 1); +} + +std::string CGeneratorBase::RemoveSpaces(const std::string& str) { + // for annotation + if (str.compare(0, 3, "/**") == 0 || + str.compare(0, 2, " *") == 0 || + str.compare(0, 3, " */") == 0) + return str; + + std::size_t found = str.find_first_not_of(' '); + if (found == std::string::npos) + return ""; + + return str.substr(found, str.size() - found); +} + std::string CGeneratorBase::Trim(const std::string& str) { + // for annotation + if (str.compare(0, 3, "/**") == 0 || + str.compare(0, 2, " *") == 0 || + str.compare(0, 3, " */") == 0) + return str; + std::size_t first = str.find_first_not_of(" \t\r\n"); if (first == std::string::npos) return str; @@ -255,10 +353,7 @@ std::string CGeneratorBase::Trim(const std::string& str) { } void CGeneratorBase::GenVersion(std::ofstream& stream) { - GenTemplate(CB_VERSION, stream, - [&]()->std::string { - return FULLVER; - }); + stream << ReplaceAll(CB_VERSION, "", FULLVER); } void CGeneratorBase::GenIncludeDefaultHeaders(std::ofstream& stream, @@ -271,19 +366,19 @@ void CGeneratorBase::GenIncludeDefaultHeaders(std::ofstream& stream, } void CGeneratorBase::GenGNUSourceDefinition(std::ofstream& stream) { - stream << NLine(1); - stream << CB_GNU_SOURCE; + stream << SmartIndent(CB_GNU_SOURCE); } -bool CGeneratorBase::StructureExist(const Structure& st) { +bool CGeneratorBase::StructureExist(const Structure* st) { for (auto& i : GetDocument().GetBlocks()) { if (i->GetType() != Block::TYPE_STRUCTURE) continue; const Structure &s = static_cast(*i); - if (s.GetID() == st.GetID()) + if (s.GetID() == st->GetID()) return true; } + return false; } @@ -293,12 +388,12 @@ std::string CGeneratorBase::GetParamTypeString( type.ToString() == "list" || type.ToString() == "array") { if (direction == ParameterType::Direction::IN) - return GetHandlePrefix() + GetFullNameFromType(type) + "_h "; + return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h "; else - return GetHandlePrefix() + GetFullNameFromType(type) + "_h *"; + return GetHandlePrefix() + "_" + GetFullNameFromType(type) + "_h *"; } - if (type.ToString() == "string") { + if (type.ToString() == "string" || type.ToString() == "file") { if (direction == ParameterType::Direction::IN) return "const char *"; else @@ -311,6 +406,41 @@ std::string CGeneratorBase::GetParamTypeString( return type_map_[type.ToString()] + "*"; } +std::string CGeneratorBase::GetParamTypeString( + ParameterType::Direction direction, const BaseType& type, + const Interface& inf) { + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + if (direction == ParameterType::Direction::IN) + return GetHandlePrefix() + "_" + GetFullNameFromType(type, inf) + "_h "; + else + return GetHandlePrefix() + "_" + GetFullNameFromType(type, inf) + "_h *"; + } + + if (type.ToString() == "string" || type.ToString() == "file") { + if (direction == ParameterType::Direction::IN) + return "const char *"; + else + return "char **"; + } + + if (direction == ParameterType::Direction::IN) + return type_map_[type.ToString()]; + + return type_map_[type.ToString()] + "*"; +} + +std::string CGeneratorBase::GetArgTypeString(const BaseType& type, + const Interface& inf) { + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") + return GetHandlePrefix() + "_" + GetFullNameFromType(type, inf) + "_h "; + + return type_map_[type.ToString()]; +} + std::string CGeneratorBase::GetErrorValue(const BaseType& type) { if (type.IsUserDefinedType() || type.ToString() == "list" || @@ -318,7 +448,7 @@ std::string CGeneratorBase::GetErrorValue(const BaseType& type) { type.ToString() == "bundle" || type.ToString() == "string"|| type.ToString() == "file") - return "NULL"; + return "nullptr"; if (type.ToString() == "bool") return "false"; if (type.ToString() == "char") @@ -326,31 +456,18 @@ std::string CGeneratorBase::GetErrorValue(const BaseType& type) { return "-1"; } -std::string CGeneratorBase::GetStringFromElementType(const BaseType& type) { - if (type.IsUserDefinedType()) - return GetHandlePrefix() + type.ToString() + "_h "; - if (type.ToString() == "array") - return GetReturnTypeString(*type.GetMetaType()) + "*"; - - return type_map_[type.ToString()]; -} - -std::string CGeneratorBase::GetStructIdWithNamespace(const Structure& st) { +std::string CGeneratorBase::GetHandlePrefix() { + std::string prefix = + IsProxy() ? PREFIX_RPC_PORT_PROXY : PREFIX_RPC_PORT_STUB; if (!HasNamespace()) - return st.GetID(); - return GetFileNamespace() + "_" + st.GetID(); -} + return prefix; -std::string CGeneratorBase::GetInterfaceIdWithNamespace(const Interface& inf) { - if (!HasNamespace()) - return inf.GetID(); - return GetFileNamespace() + "_" + inf.GetID(); + return prefix + "_" + GetFileNamespace() + "_"; } -std::string CGeneratorBase::GetHandlePrefix() { - if (!HasNamespace()) - return "rpc_port_"; - return "rpc_port_" + GetFileNamespace() + "_"; +const std::map>& +CGeneratorBase::GetStructures() { + return structures_; } } // namespace tidl diff --git a/idlc/gen/c_gen_base.h b/idlc/gen/c_gen_base.h index caec1452..651892eb 100644 --- a/idlc/gen/c_gen_base.h +++ b/idlc/gen/c_gen_base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,9 @@ #ifndef IDLC_C_GEN_C_GEN_BASE_H_ #define IDLC_C_GEN_C_GEN_BASE_H_ +#include #include #include -#include #include "idlc/ast/type.h" #include "idlc/ast/structure.h" @@ -32,34 +32,38 @@ class CGeneratorBase : public Generator { explicit CGeneratorBase(std::shared_ptr doc); virtual ~CGeneratorBase() = default; - std::string Trim(const std::string& str); + std::string RemoveLine(std::string lines, unsigned int line_num = 1); std::string SmartIndent(std::string lines); - std::string Tab(int cnt); std::string NLine(int cnt); - std::string ConvertTypeToString(ParameterType::Direction direction, - const BaseType& type, bool bconst = true); + std::string GetFullNameFromType(const BaseType& type); - std::string GetParcelParamTypeString(const BaseType& type, - bool is_pointer = true); + std::string GetFullNameFromType(const BaseType& type, const Interface& inf); + + std::string GetDataTypeString(const BaseType& type, bool is_pointer = true); std::string GetReturnTypeString(const BaseType& type); std::string GetParamTypeString(ParameterType::Direction direction, - const BaseType& type); - std::string GetStringFromElementType(const BaseType& type); + const BaseType& type); + std::string GetParamTypeString(ParameterType::Direction direction, + const BaseType& type, const Interface& inf); + std::string GetArgTypeString(const BaseType& type, const Interface& inf); std::string GetErrorValue(const BaseType& type); + void AddStructureFromType(const BaseType& type); - const std::map>& GetStructures(void) { - return structures_; - } + void AddStructureFromType(const BaseType& type, const Interface& inf); + + const std::map>& GetStructures(); void GenVersion(std::ofstream& stream); void GenIncludeDefaultHeaders(std::ofstream& stream, bool body = true); void GenGNUSourceDefinition(std::ofstream& stream); - std::string GetStructIdWithNamespace(const Structure& st); - std::string GetInterfaceIdWithNamespace(const Interface& inf); std::string GetHandlePrefix(); + std::string RemoveLastSpaces(const std::string& str); private: - bool StructureExist(const Structure& st); + std::string Tab(int cnt); + std::string Trim(const std::string& str); + std::string RemoveSpaces(const std::string& str); + bool StructureExist(const Structure* st); private: std::map> structures_; diff --git a/idlc/gen/c_gen_base_cb.h b/idlc/gen/c_gen_base_cb.h index f258cb6f..1ae1ddb6 100644 --- a/idlc/gen/c_gen_base_cb.h +++ b/idlc/gen/c_gen_base_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,26 +17,30 @@ #ifndef IDLC_C_GEN_C_GEN_BASE_CB_H_ #define IDLC_C_GEN_C_GEN_BASE_CB_H_ -const char CB_VERSION[] = +/** + * Version of TIDL Compiler. + */ +constexpr const char CB_VERSION[] = R"__c_cb(/* - * Generated by tidlc $$. + * Generated by tidlc . */ )__c_cb"; -const char CB_GNU_SOURCE[] = +constexpr const char CB_GNU_SOURCE[] = R"__c_cb( #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif )__c_cb"; -const char CB_HEADER[] = +constexpr const char CB_HEADER[] = R"__c_cb( #include #include +#include )__c_cb"; -const char CB_BODY_HEADER[] = +constexpr const char CB_BODY_HEADER[] = R"__c_cb( #include #include diff --git a/idlc/gen/c_header_gen_base.cc b/idlc/gen/c_header_gen_base.cc index f402fe08..4d09a80d 100644 --- a/idlc/gen/c_header_gen_base.cc +++ b/idlc/gen/c_header_gen_base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include "idlc/gen/c_header_gen_base.h" @@ -25,7 +27,28 @@ namespace { namespace tidl { CHeaderGeneratorBase::CHeaderGeneratorBase(std::shared_ptr doc) - : CGeneratorBase(doc) {} + : CGeneratorBase(doc) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() == Block::TYPE_STRUCTURE) { + auto& st = static_cast(*b); + for (auto& e : st.GetElements().GetElms()) { + auto& type = e->GetType(); + AddStructureFromType(type); + } + } else { + auto& inf = static_cast(*b); + for (auto& d : inf.GetDeclarations().GetDecls()) { + for (auto& p : d->GetParameters().GetParams()) { + auto& type = p->GetParameterType().GetBaseType(); + if (IsDelegateType(inf, type)) + continue; + + AddStructureFromType(type, inf); + } + } + } + } +} void CHeaderGeneratorBase::GenPragmaOnce(std::ofstream& stream) { const char format[] = "#pragma once\n"; @@ -42,249 +65,106 @@ void CHeaderGeneratorBase::GenExplicitLinkageClose(std::ofstream& stream) { stream << CB_EXPLICIT_LINKAGE_CLOSE; } -void CHeaderGeneratorBase::GenStructures(std::ofstream& stream) { - for (auto& i : GetDocument().GetBlocks()) { - if (i->GetType() == Block::TYPE_STRUCTURE) { - const Structure &st = static_cast(*i); - GenStructure(stream, st); - for (auto& j : st.GetElements().GetElms()) { - auto& t = j->GetType(); - AddStructureFromType(t); - } - } else { - const Interface &inf = static_cast(*i); - for (auto& d : inf.GetDeclarations().GetDecls()) { - for (auto& p : d->GetParameters().GetParams()) { - if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) - continue; - AddStructureFromType(p->GetParameterType().GetBaseType()); - } - } +void CHeaderGeneratorBase::GenStructureHandles(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() == Block::TYPE_STRUCTURE) { + auto& st = static_cast(*b); + GenStructureHandle(stream, st); } } - for (auto& p : GetStructures()) { - const Structure& st = *p.second; - GenStructure(stream, st); + for (auto& i : GetStructures()) { + auto& st = i.second; + GenStructureHandle(stream, *st); } } -void CHeaderGeneratorBase::GenStructure(std::ofstream& stream, - const Structure& st) { - GenStructureDeclaration(stream, st); - GenStructureConstructor(stream, st); - GenStructureDestructor(stream, st); - GenStructureCloner(stream, st); - GenStructureSetter(stream, st); - GenStructureGetter(stream, st); - GenStructureIterator(stream, st); - GenStructureRemover(stream, st); - GenStructureLengthGetter(stream, st); -} - -void CHeaderGeneratorBase::GenStructureDeclaration(std::ofstream& stream, - const Structure& st) { - GenTemplate(CB_STRUCT_DECL, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }); -} - -void CHeaderGeneratorBase::GenStructureConstructor(std::ofstream& stream, - const Structure& st) { - GenTemplate(CB_STRUCT_CTOR, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }); -} - -void CHeaderGeneratorBase::GenStructureDestructor(std::ofstream& stream, - const Structure& st) { - GenTemplate(CB_STRUCT_DTOR, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }); -} - -void CHeaderGeneratorBase::GenStructureSetter(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - GenTemplate(CB_STRUCT_SETTER, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().ToString() == "list") - return "add"; - return "set"; - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().IsUserDefinedType()) - return GetParcelParamTypeString(i->GetType()); - - if (i->GetType().ToString() == "list") { - if (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array") { - return GetParcelParamTypeString(*i->GetType().GetMetaType()); - } else { - return ConvertTypeToString(ParameterType::Direction::IN, - *i->GetType().GetMetaType()); - } - } - - if (i->GetType().ToString() == "array") { - return GetStringFromElementType(i->GetType()); - } - - return ConvertTypeToString(ParameterType::Direction::IN, - i->GetType()); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") { - std::string str; - str += i->GetID(); - str += ", "; - str += "int " + i->GetID() + "_size"; - return str; - } - return i->GetID(); - }); +void CHeaderGeneratorBase::GenStructures(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() == Block::TYPE_STRUCTURE) { + auto& st = static_cast(*b); + GenStructure(stream, st); + } } -} -void CHeaderGeneratorBase::GenStructureGetter(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() == "list") - continue; - - GenTemplate(CB_STRUCT_GETTER, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") - return GetStringFromElementType(i->GetType()) + "*"; - - return ConvertTypeToString(ParameterType::Direction::OUT, - i->GetType()); - }, - [&]()->std::string { - if (i->GetType().ToString() == "array") { - std::string str; - str += i->GetID(); - str += ", "; - str += "int *" + i->GetID() + "_size"; - return str; - } - return i->GetID(); - }); + for (auto& i : GetStructures()) { + auto& st = i.second; + GenStructure(stream, *st); } } -void CHeaderGeneratorBase::GenStructureIterator(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() != "list") - continue; +// @see #CB_STRUCTURE_HANDLE +void CHeaderGeneratorBase::GenStructureHandle(std::ofstream& stream, + const Structure& st) { + std::string str = ReplaceAll(CB_STRUCTURE_HANDLE, "", + GetHandlePrefix()); + str = ReplaceAll(str, "", st.GetID()); + stream << SmartIndent(str); +} - GenTemplate(CB_STRUCT_ITERATOR, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - if (i->GetType().GetMetaType()->IsUserDefinedType() || - i->GetType().GetMetaType()->ToString() == "list" || - i->GetType().GetMetaType()->ToString() == "array") - return GetParcelParamTypeString(*i->GetType().GetMetaType()); +// @see #CB_STRUCTURE_ARRAY_BASE +void CHeaderGeneratorBase::GenStructureArrayBase(std::ofstream& stream, + const Structure& st) { + std::string str = ReplaceAll(CB_STRUCTURE_ARRAY_BASE, "", + GetHandlePrefix()); + str = ReplaceAll(str, "", st.GetID()); - return ConvertTypeToString(ParameterType::Direction::IN, - *i->GetType().GetMetaType()); - }, - [&]()->std::string { - return i->GetID(); - }); - } -} + auto& elm = st.GetElements().GetElms().front(); + auto& type = elm->GetType(); + auto param_type = GetParamTypeString(ParameterType::Direction::IN, type); + str = ReplaceAll(str, "", param_type); -void CHeaderGeneratorBase::GenStructureRemover(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() != "list") - continue; + param_type = GetParamTypeString(ParameterType::Direction::OUT, type); + str = ReplaceAll(str, "", param_type); - GenTemplate(CB_STRUCT_REMOVER, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }); - } + stream << SmartIndent(str); } -void CHeaderGeneratorBase::GenStructureLengthGetter(std::ofstream& stream, - const Structure& st) { - for (auto& i : st.GetElements().GetElms()) { - if (i->GetType().ToString() != "list") - continue; +// @see #CB_STRUCTURE_LIST_BASE +void CHeaderGeneratorBase::GenStructureListBase(std::ofstream& stream, + const Structure& st) { + std::string str = ReplaceAll(CB_STRUCTURE_LIST_BASE, "", + GetHandlePrefix()); + str = ReplaceAll(str, "", st.GetID()); + + auto& elm = st.GetElements().GetElms().front(); + auto& type = elm->GetType(); + auto param_type = GetParamTypeString(ParameterType::Direction::IN, type); + str = ReplaceAll(str, "", param_type); + stream << SmartIndent(str); +} - GenTemplate(CB_STRUCT_LENGTH_GETTER, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }); +// @see #CB_STRUCTURE_BASE +void CHeaderGeneratorBase::GenStructureBase(std::ofstream& stream, + const Structure& st) { + std::string str = ReplaceAll(CB_STRUCTURE_BASE, "", + GetHandlePrefix()); + str = ReplaceAll(str, "", st.GetID()); + stream << SmartIndent(str); + + for (auto& e : st.GetElements().GetElms()) { + str = ReplaceAll(CB_STRUCTURE_BASE_SET_GET, "", GetHandlePrefix()); + str = ReplaceAll(str, "", st.GetID()); + + auto& type = e->GetType(); + auto param_type = GetParamTypeString(ParameterType::Direction::IN, type); + str = ReplaceAll(str, "", param_type); + + param_type = GetParamTypeString(ParameterType::Direction::OUT, type); + str = ReplaceAll(str, "", param_type); + str = ReplaceAll(str, "", e->GetID()); + stream << SmartIndent(str); } } -void CHeaderGeneratorBase::GenStructureCloner(std::ofstream& stream, - const Structure& st) { - GenTemplate(CB_STRUCT_CLONER, stream, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }, - [&]()->std::string { - return GetStructIdWithNamespace(st); - }); +void CHeaderGeneratorBase::GenStructure(std::ofstream& stream, + const Structure& st) { + if (st.GetID().compare(0, strlen("array"), "array") == 0) + GenStructureArrayBase(stream, st); + else if (st.GetID().compare(0, strlen("list"), "list") == 0) + GenStructureListBase(stream, st); + else + GenStructureBase(stream, st); } } // namespace tidl diff --git a/idlc/gen/c_header_gen_base.h b/idlc/gen/c_header_gen_base.h index 4e2ad35e..b61571ca 100644 --- a/idlc/gen/c_header_gen_base.h +++ b/idlc/gen/c_header_gen_base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,21 +33,15 @@ class CHeaderGeneratorBase : public CGeneratorBase { void GenPragmaOnce(std::ofstream& stream); void GenExplicitLinkageOpen(std::ofstream& stream); void GenExplicitLinkageClose(std::ofstream& stream); + void GenStructureHandles(std::ofstream& stream); void GenStructures(std::ofstream& stream); private: + void GenStructureHandle(std::ofstream& stream, const Structure& st); + void GenStructureArrayBase(std::ofstream& stream, const Structure& st); + void GenStructureListBase(std::ofstream& stream, const Structure& st); + void GenStructureBase(std::ofstream& stream, const Structure& st); void GenStructure(std::ofstream& stream, const Structure& st); - void GenStructureDeclaration(std::ofstream& stream, const Structure& st); - void GenStructureParcelTo(std::ofstream& stream, const Structure& st); - void GenStructureParcelFrom(std::ofstream& stream, const Structure& st); - void GenStructureConstructor(std::ofstream& stream, const Structure& st); - void GenStructureDestructor(std::ofstream& stream, const Structure& st); - void GenStructureSetter(std::ofstream& stream, const Structure& st); - void GenStructureGetter(std::ofstream& stream, const Structure& st); - void GenStructureIterator(std::ofstream& stream, const Structure& st); - void GenStructureRemover(std::ofstream& stream, const Structure& st); - void GenStructureLengthGetter(std::ofstream& stream, const Structure& st); - void GenStructureCloner(std::ofstream& stream, const Structure& st); }; } // namespace tidl diff --git a/idlc/gen/c_header_gen_base_cb.h b/idlc/gen/c_header_gen_base_cb.h index e0229f59..fe167601 100644 --- a/idlc/gen/c_header_gen_base_cb.h +++ b/idlc/gen/c_header_gen_base_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,64 +17,327 @@ #ifndef IDLC_C_GEN_C_HEADER_GEN_BASE_CB_H_ #define IDLC_C_GEN_C_HEADER_GEN_BASE_CB_H_ -const char CB_EXPLICIT_LINKAGE_OPEN[] = +constexpr const char CB_EXPLICIT_LINKAGE_OPEN[] = R"__c_cb( #ifdef __cplusplus extern "C" { #endif )__c_cb"; -const char CB_EXPLICIT_LINKAGE_CLOSE[] = +constexpr const char CB_EXPLICIT_LINKAGE_CLOSE[] = R"__c_cb( #ifdef __cplusplus } #endif )__c_cb"; -const char CB_STRUCT_DECL[] = -R"__c_cb( -typedef struct $$_s *rpc_port_$$_h; -)__c_cb"; -const char CB_STRUCT_CTOR[] = +/** + * The prefix of the handle. + * The name of the handle. + */ +constexpr const char CB_STRUCTURE_HANDLE[] = R"__c_cb( -int rpc_port_$$_create(rpc_port_$$_h *h); +/** + * @brief The _ handle. + */ +typedef struct __s *__h; )__c_cb"; -const char CB_STRUCT_DTOR[] = +/** + * The prefix of the array structure. + * The name of the array structure. + * The type of the input parameter. + * The type of the output parameter. + */ +constexpr const char CB_STRUCTURE_ARRAY_BASE[] = R"__c_cb( -int rpc_port_$$_destroy(rpc_port_$$_h h); -)__c_cb"; +/** + * @briefs Creates a _ handle. + * + * @remarks The @a h should be released using the __destroy() + * if it's no longer needed. + * @param[out] h The _ handle that is newly created + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __destroy() + */ +int __create(__h *h); -const char CB_STRUCT_SETTER[] = -R"__c_cb( -int rpc_port_$$_$$_$$(rpc_port_$$_h h, $$$$); -)__c_cb"; +/** + * @brief Destroys the _ handle. + * + * @param[in] h The _ 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 __create() + */ +int __destroy(__h h); -const char CB_STRUCT_GETTER[] = -R"__c_cb( -int rpc_port_$$_get_$$(rpc_port_$$_h h, $$$$); -)__c_cb"; +/** + * @brief Creates and returns a copy of the given _ handle. + * + * @remarks A new created _ should be released using + * the __destroy() if it's no longer needed. + * @param[in] h The _ handle + * @param[out] clone If successful, a new created _ 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 __destroy() + */ +int __clone(__h h, __h *clone); -const char CB_STRUCT_ITERATOR[] = -R"__c_cb( -int rpc_port_$$_foreach_$$(rpc_port_$$_h h, - bool (*callback)($$$$, void *user_data), void *user_data); +/** + * @brief Sets the value to the _ handle. + * + * @remarks The value is internally copied and stored. + * You should release it if it's allocaed when it's no longer needed, + * @param[in] h The _ handle + * @param[in] value The array value + * @param[in] size The size of the array + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __get() + */ +int __set(__h h, *value, int size); + +/** + * @brief Gets the value from the _ handle. + * + * @remarks A new created value should be released if it's no longer needed. + * @param[in] h The _ handle + * @param[out] value The array value + * @param[out] size The size of the array + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __set() + */ +int __get(__h h, *value, int *size); )__c_cb"; -const char CB_STRUCT_REMOVER[] = +/** + * The prefix of the list structure. + * The name of the list structure. + * The type of the input parameter. + */ +constexpr const char CB_STRUCTURE_LIST_BASE[] = R"__c_cb( -int rpc_port_$$_remove_$$(rpc_port_$$_h h, unsigned int nth); +/** + * @brief Called to retrieve the value contained in the _ handle. + * + * @remarks The @a value MUST NOT be released by the application. + * @param[in] value The value of the list + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, + * otherwise @c false to break out of the loop + * @see __foreach() + */ +typedef bool (*__cb)(value, void *user_data); + +/** + * @brief Creates a _ handle. + * + * @remarks The @a h handle should be released using the __destroy() + * if it's no longer needed. + * @param[out] h The _ handle that is newly created + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __destroy() + */ +int __create(__h *h); + +/** + * @brief Destroys the _ handle. + * + * @param[in] The _ 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 __create() + */ +int __destroy(__h h); + +/** + * @brief Creates and returns a copy of the given _ handle. + * + * @remarks A new created _ should be released using + * the __destroy() if it's no longer needed. + * @param[in] h The _ handle + * @param[out] clone If successful, a new created _ 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 __destroy() + */ +int __clone(__h h, __h *clone); + +/** + * @brief Adds the value to the _ handle. + * + * @remarks The value is internally copied and stored. + * You should release it if it's allocaed when it's no longer needed, + * @param[in] h The _ handle. + * @param[in] value The value + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __remove() + */ +int __add(__h h, value); + +/** + * @brief Retrieves all values contained in the _ handle. + * @details This function called __cb once for each value contained in the _ handle. + * If the __cb callback function returns @c false, the iteration will be finished. + * + * @param[in] h The _ 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 __cb() + */ +int __foreach(__h h, __cb callback, void *user_data); + +/** + * @brief Removes the element at the given position in the _ handle. + * + * @param[in] h The _ handle + * @param[in] nth The position of the element + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int __remove(__h h, unsigned int nth); + +/** + * @brief Gets the number of elements in the _ handle. + * + * @param[in] h The _ handle + * @param[out] length The number of elements + * @return @c on 0 success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int __length(__h h, unsigned int *length); )__c_cb"; -const char CB_STRUCT_LENGTH_GETTER[] = +/** + * The prefix of the structure. e.g. rpc_port_proxy_ or rpc_port_stub_ + * The name of the structure. + */ +constexpr const char CB_STRUCTURE_BASE[] = R"__c_cb( -int rpc_port_$$_get_$$_length(rpc_port_$$_h h, unsigned int *length); +/** + * @brief Creates a _ handle. + * + * @remarks The @a h handle should be released using the __destroy() + * if it's no longer needed. + * @param[out] h The _ handle that is newly created + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMTER Invaid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __destroy() + */ +int __create(__h *h); + +/** + * @brief Destroys the _ handle. + * + * @param[in] h The _ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __create() + */ +int __destroy(__h h); + +/** + * @brief Creates and returns a copy of the given _ handle. + * + * @remarks A new created _ should be released using + * the __destroy() if it's no longer needed. + * @param[in] h The _ handle + * @param[out] clone If successful, a new created _ 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 __destroy() + */ +int __clone(__h h, __h *clone); )__c_cb"; -const char CB_STRUCT_CLONER[] = +/** + * The prefix of the structure. e.g. rpc_port_proxy_ or rpc_port_stub_ + * The name of the structure. + * The type of the input parameter. + * The type of the output parameter. + * The name of the element of the structure. + */ +constexpr const char CB_STRUCTURE_BASE_SET_GET[] = R"__c_cb( -int rpc_port_$$_clone(rpc_port_$$_h h, rpc_port_$$_h *clone); +/** + * @brief Sets the to the _ handle. + * + * @remarks The is internally copied and stored. + * You should release it if it's allocated when it's no longer needed. + * @param[in] h The _ handle + * @param[in] value The + * @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 __get_() + */ +int __set_(__h h, value); + +/** + * @brief Gets the from the _ handle. + * + * @remarks A new created value should be released if it's allocated when it's no longer needed. + * @param[in] h The _ handle + * @param[out] value The + * @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 __set_ + */ +int __get_(__h h, value); )__c_cb"; #endif // IDLC_C_GEN_C_HEADER_GEN_BASE_CB_H_ diff --git a/idlc/gen/c_proxy_body_gen.cc b/idlc/gen/c_proxy_body_gen.cc index 7c775f57..a6d46a53 100644 --- a/idlc/gen/c_proxy_body_gen.cc +++ b/idlc/gen/c_proxy_body_gen.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,17 @@ * limitations under the License. */ -#include "idlc/gen/c_proxy_body_gen.h" +#include -namespace { +#include "idlc/gen/c_proxy_body_gen.h" #include "idlc/gen/c_proxy_body_gen_cb.h" -} namespace tidl { -CProxyBodyGen::CProxyBodyGen(std::shared_ptr doc) - : CBodyGeneratorBase(doc) {} +CProxyBodyGen::CProxyBodyGen(std::shared_ptr doc, + std::shared_ptr options) + : CBodyGeneratorBase(doc), options_(std::move(options)) { +} void CProxyBodyGen::OnInitGen(std::ofstream& stream) { GenVersion(stream); @@ -32,7 +33,11 @@ void CProxyBodyGen::OnInitGen(std::ofstream& stream) { GenIncludeHeader(stream); GenLogTag(stream, std::string("RPC_PORT_PROXY")); GenLogDefinition(stream); - GenTypedefProxyDelegate(stream); + GenBaseDefinition(stream); + GenInterfaceDelegateCallback(stream); + GenStructureDefs(stream); + GenInterfaceDefs(stream); + GenPrivateSharingListSet(stream); GenStructures(stream); GenInterfaces(stream); } @@ -40,558 +45,555 @@ void CProxyBodyGen::OnInitGen(std::ofstream& stream) { void CProxyBodyGen::OnFiniGen(std::ofstream& stream) { } -void CProxyBodyGen::GenTypedefProxyDelegate(std::ofstream& stream) { - const char format[] = - "typedef void (*proxy_delegate)(GList **list, rpc_port_parcel_h parcel," \ - " int seq_id, int id);\n"; - stream << NLine(1); - stream << std::string(format); +// @see #CB_INTERFACE_DELEGATE_CALLBACK +void CProxyBodyGen::GenInterfaceDelegateCallback(std::ofstream& stream) { + stream << SmartIndent(CB_INTERFACE_DELEGATE_CALLBACK); } -void CProxyBodyGen::GenInterfaces(std::ofstream& stream) { +void CProxyBodyGen::GenInterfaceDefs(std::ofstream& stream) { for (auto& i : GetDocument().GetBlocks()) { if (i->GetType() != Block::TYPE_INTERFACE) continue; const Interface &inf = static_cast(*i); - GenInterface(stream, inf); + GenInterfaceDef(stream, inf); } } -void CProxyBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) { - GenInterfaceFileSharing(stream, inf); - GenInterfaceEnumerations(stream, inf); - GenInterfaceDeclaration(stream, inf); - GenInterfaceDelegators(stream, inf); - GenInterfaceDelegatorTable(stream, inf); - GenInterfaceDelegatorHandler(stream, inf); - GenInterfaceConsumeCommand(stream, inf); - GenInterfaceOnConnectedEventCB(stream, inf); - GenInterfaceOnDisconnectedEventCB(stream, inf); - GenInterfaceOnRejectedEventCB(stream, inf); - GenInterfaceOnReceivedEventCB(stream, inf); - GenInterfaceMethods(stream, inf); - GenInterfaceHandleCtor(stream, inf); - GenInterfaceHandleDtor(stream, inf); - GenInterfaceCtor(stream, inf); - GenInterfaceConnect(stream, inf); - GenInterfaceDtor(stream, inf); - GenInterfaceConnectSync(stream, inf); -} +void CProxyBodyGen::GenInterfaceDef(std::ofstream& stream, + const Interface& inf) { + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; -void CProxyBodyGen::GenInterfaceFileSharing(std::ofstream& stream, - const Interface& inf) { - - for (auto& i : inf.GetDeclarations().GetDecls()) { - for (auto& p : i->GetParameters().GetParams()) { - if ((p->GetParameterType().GetBaseType().ToString() == "list" || - p->GetParameterType().GetBaseType().ToString() == "array") && - p->GetParameterType().GetBaseType().GetMetaType()->ToString() == "file") { - if (p->GetParameterType().GetBaseType().ToString() == "array") { - stream << SmartIndent(std::string(CB_FILE_ARRAY_SHARING)); - } else { - stream << SmartIndent(std::string(CB_FILE_LIST_SHARING)); - } - } - } + GenInterfaceDelegateDef(stream, inf, *d); } + + GenInterfaceBaseDef(stream, inf); } +// @see #CB_INTERFACE_DELEGATE_DEF +void CProxyBodyGen::GenInterfaceDelegateDef(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); -void CProxyBodyGen::GenInterfaceDeclaration(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_STRUCT, "##", - GetInterfaceIdWithNamespace(inf))); + stream << SmartIndent(code); } -void CProxyBodyGen::GenInterfaceDelegators(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) - continue; - GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i); - } -} +// @see #CB_INTERFACE_BASE_DEF +void CProxyBodyGen::GenInterfaceBaseDef(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_BASE_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); -void CProxyBodyGen::GenInterfaceDelegator(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - GenInterfaceDelegatorDeclaration(stream, id, decl); - GenInterfaceDelegatorSerializer(stream, id, decl); - GenInterfaceDelegatorDeserializer(stream, id, decl); - GenInterfaceDelegatorConstructor(stream, id, decl); - GenInterfaceDelegatorDestructor(stream, id, decl); - GenInterfaceDelegatorDisposer(stream, id, decl); - GenInterfaceDelegatorInvoker(stream, id, decl); + stream << SmartIndent(code); } -void CProxyBodyGen::GenInterfaceDelegatorDeclaration( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << SmartIndent(ReplaceAll( - CB_DELEGATE_STRUCT, "##", id + "_" + decl.GetID())); -} +void CProxyBodyGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; -void CProxyBodyGen::GenInterfaceDelegatorSerializer( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << SmartIndent( - ReplaceAll(CB_DELEGATE_SERIALIZER, "##", id + "_" + decl.GetID())); + const Interface &inf = static_cast(*i); + GenInterface(stream, inf); + } } -void CProxyBodyGen::GenInterfaceDelegatorDeserializer( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << SmartIndent( - ReplaceAll(CB_DELEGATE_DESERIALIZER, "##", id + "_" + decl.GetID())); -} +void CProxyBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) { + GenInterfaceDelegateEnumBase(stream, inf); -void CProxyBodyGen::GenInterfaceDelegatorConstructor( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_DELEGATE_CTOR, "##", id + "_" + decl.GetID()), - [&]()->std::string { - return id; - }, - [&]()->std::string { - return decl.GetID(); - })); -} + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; -void CProxyBodyGen::GenInterfaceDelegatorDisposer( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_DELEGATE_DISPOSER, "##", id + "_" + decl.GetID()), - [&]()->std::string { - return id; - })); -} + GenInterfaceDelegateBase(stream, inf, *d); + } -void CProxyBodyGen::GenInterfaceDelegatorInvoker( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - const char parcel[] = "$$(parcel, $$);\n"; - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_DELEGATE_INVOKER, "##", id + "_" + decl.GetID()), - [&]()->std::string { - return id; - }, - [&]()->std::string { - return decl.GetID(); - }, - [&]()->std::string { - std::string str; - int cnt = 0; - for (auto& i : decl.GetParameters().GetParams()) { - str += GetParcelParamTypeString( - i->GetParameterType().GetBaseType(), false) + i->GetID(); - str += " = " + GetErrorValue(i->GetParameterType().GetBaseType()); - str += ";" + NLine(1); - cnt++; - } - if (cnt > 0) - str += NLine(1); - for (auto& i : decl.GetParameters().GetParams()) { - if (i->GetParameterType().GetBaseType().IsUserDefinedType() || - i->GetParameterType().GetBaseType().ToString() == "list" || - i->GetParameterType().GetBaseType().ToString() == "array") { - str += GetConstructorString(i->GetParameterType().GetBaseType(), - i->GetID()); - } - str += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelReadFunctionString( - i->GetParameterType().GetBaseType(), true); - }, - [&]()->std::string { - if (i->GetParameterType().GetBaseType().IsUserDefinedType() || - i->GetParameterType().GetBaseType() - .ToString() == "list" || - i->GetParameterType().GetBaseType().ToString() == "array") - return "&" + i->GetID() + "->parcelable, " + i->GetID(); - return "&" + i->GetID(); - }); - } - return str; - }, - [&]()->std::string { - std::string str; - str += "handle->callback(handle->user_data"; - for (auto& i : decl.GetParameters().GetParams()) { - str += ", "; - str += i->GetID(); - } - str += ");" + NLine(1); - return str; - }, - [&]()->std::string { - std::string str; - for (auto& i : decl.GetParameters().GetParams()) { - str += GetDestructorString(i->GetParameterType().GetBaseType(), - i->GetID()); - str += NLine(1); - } - return str; - })); -} + GenInterfaceDelegateTable(stream, inf); + GenInterfaceMethodEnumBase(stream, inf); + GenInterfaceBase(stream, inf); -void CProxyBodyGen::GenInterfaceDelegatorDestructor( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << SmartIndent(ReplaceAll( - CB_DELEGATE_DTOR, "##", id + "_" + decl.GetID())); + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceMethodBase(stream, inf, *d); + } } -void CProxyBodyGen::GenInterfaceDelegatorTable(std::ofstream& stream, - const Interface& inf) { - const char block[] = - "static proxy_delegate __$$_delegate_table[] = {\n" \ - "$$" \ - "};\n"; - const char delegate_format[] = "[$$] = $$,\n"; - std::string str; - int cnt = 0; - - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) +// @see #CB_INTERFACE_BASE +void CProxyBodyGen::GenInterfaceBase(std::ofstream& stream, + const Interface& inf) { + std::string prefix = GetHandlePrefix(); + std::string code = ReplaceAll(CB_INTERFACE_BASE, "", prefix); + std::string name = inf.GetID(); + code = ReplaceAll(code, "", name); + std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper); + code = ReplaceAll(code, "", prefix); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + code = ReplaceAll(code, "", name); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_DELEGATE_ENUM_BASE +void CProxyBodyGen::GenInterfaceDelegateEnumBase(std::ofstream& stream, + const Interface& inf) { + unsigned int num = 1; + std::string enums; + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) continue; - str += GenTemplateString(delegate_format, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf) + "_DELEGATE_" + i->GetID(); - }, - [&]()->std::string { - return "__" + GetInterfaceIdWithNamespace(inf) + "_delegate_" - + i->GetID(); - }); - cnt++; + + enums += GetHandlePrefix() + "_" + inf.GetID() + "_DELEGATE_" + d->GetID(); + enums += " = " + std::to_string(num++) + ","; + enums += NLine(1); } - if (cnt == 0) + if (enums.empty()) return; - stream << NLine(1); - stream << SmartIndent(GenTemplateString(block, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return str; - })); -} + std::transform(enums.begin(), enums.end(), enums.begin(), ::toupper); + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_ENUM_BASE, "", + enums); + code = ReplaceAll(code, "", GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); -void CProxyBodyGen::GenInterfaceDelegatorHandler(std::ofstream& stream, - const Interface& inf) { - std::string str; - int cnt = 0; + stream << SmartIndent(code); +} - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) - continue; - cnt++; +std::string CProxyBodyGen::GenDelegateArgsDecl(const Interface& inf, + const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + code += GetArgTypeString(type, inf) + p->GetID() + " = " + + GetErrorValue(param_type.GetBaseType()) + ";" + NLine(1); } - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_PROCESS_RECEIVED_EVENT, "##", - GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - if (cnt == 0) - return str; - return ReplaceAll(CB_PROCESS_RECEIVED_EVENT_IMPL, "##", - GetInterfaceIdWithNamespace(inf)); - })); + return code; } -void CProxyBodyGen::GenInterfaceConsumeCommand(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_CONSUME_COMMAND, "##", - GetInterfaceIdWithNamespace(inf))); -} +// @see #CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_READ +// @see #CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_READ +// @see #CB_INTERFACE_DELEGATE_STRING_PARCEL_READ +// @see #CB_INTERFACE_DELEGATE_BASE_PARCEL_READ +std::string CProxyBodyGen::GenDelegateParcelRead(const Interface& inf, + const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + std::string param_read_code; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + param_read_code = ReplaceAll( + CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + + std::string name = GetFullNameFromType(type, inf); + param_read_code = ReplaceAll(param_read_code, "", name); + param_read_code = ReplaceAll(param_read_code, "", p->GetID()); + } else if (type.ToString() == "bundle") { + param_read_code = ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_READ, + "", p->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + param_read_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_PARCEL_READ, + "", p->GetID()); + } else { + param_read_code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE_PARCEL_READ, + "", GetParcelType(type)); + param_read_code = ReplaceAll(param_read_code, "", p->GetID()); + } -void CProxyBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_ON_CONNECTED, "##", - GetInterfaceIdWithNamespace(inf))); -} + code += param_read_code; + } -void CProxyBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_ON_DISCONNECTED, "##", - GetInterfaceIdWithNamespace(inf))); + return RemoveLine(code); } -void CProxyBodyGen::GenInterfaceOnRejectedEventCB(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_ON_REJECTED, "##", - GetInterfaceIdWithNamespace(inf))); -} +// @see CB_INTERFACE_DELEGATE_USER_DEFINED_ARG_FREE +// @see CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE +// @see CB_INTERFACE_DELEGATE_STRING_ARG_FREE +std::string CProxyBodyGen::GenDelegateArgsFree(const Interface& inf, + const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + std::string param_free_code; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + param_free_code = ReplaceAll( + CB_INTERFACE_DELEGATE_USER_DEFINED_ARG_FREE, "", + GetHandlePrefix()); + + std::string name = GetFullNameFromType(type, inf); + param_free_code = ReplaceAll(param_free_code, "", name); + param_free_code = ReplaceAll(param_free_code, "", p->GetID()); + } else if (type.ToString() == "bundle") { + param_free_code = ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE, + "", p->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + param_free_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_ARG_FREE, + "", p->GetID()); + } -void CProxyBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_ON_RECEIVED, "##", - GetInterfaceIdWithNamespace(inf))); -} + code += param_free_code; + } -void CProxyBodyGen::GenInterfaceMethods(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) + return RemoveLine(code); +} + +std::string CProxyBodyGen::GenDelegateCallbackArgs(const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) + code += ", " + p->GetID(); + + return code; +} + +// @see CB_INTERFACE_DELEGATE_BASE +void CProxyBodyGen::GenInterfaceDelegateBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + + std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() + + "_DELEGATE_" + decl.GetID(); + std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(), + ::toupper); + code = ReplaceAll(code, "", enum_value); + code = ReplaceAll(code, "", + GenDelegateArgsDecl(inf, decl)); + code = ReplaceAll(code, "", + GenDelegateParcelRead(inf, decl)); + code = ReplaceAll(code, "", + GenDelegateArgsFree(inf, decl)); + code = ReplaceAll(code, "", + GenDelegateCallbackArgs(decl)); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_DELEGATE_TABLE +// @see #CB_INTERFACE_DELEGATE_TABLE_MEMBER +void CProxyBodyGen::GenInterfaceDelegateTable(std::ofstream& stream, + const Interface& inf) { + std::string delegate_handlers; + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) continue; - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_INTERFACE_METHODS, "##", - GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - return GetReturnTypeString(i->GetType()); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - std::string str; - for (auto& p : i->GetParameters().GetParams()) { - str += ", "; - if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) { - str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" + - p->GetParameterType().GetBaseType().ToString() + - "_h " + p->GetID(); - } else { - str += GetParamTypeString(p->GetParameterType().GetDirection(), - p->GetParameterType().GetBaseType()) + p->GetID(); - } - } - return str; - }, - [&]()->std::string { - if (GetReturnTypeString(i->GetType()) != "void ") - return GetReturnTypeString(i->GetType()) + "ret = " + - GetErrorValue(i->GetType()) + ";"; - return ""; - }, - [&]()->std::string { - std::string str; - for (auto& p : i->GetParameters().GetParams()) { - if (p->GetParameterType().GetDirection() == - ParameterType::Direction::OUT || - p->GetParameterType().GetBaseType().IsUserDefinedType() || - p->GetParameterType().GetBaseType().ToString() == "list" || - p->GetParameterType().GetBaseType().ToString() == "array" || - p->GetParameterType().GetBaseType().ToString() == "bundle") - str += " || !" + p->GetID(); - } - return str; - }, - [&]()->std::string { - if (GetReturnTypeString(i->GetType()) != "void ") - return " ret"; - return ""; - }, - [&]()->std::string { - if (GetReturnTypeString(i->GetType()) != "void ") - return " ret"; - return ""; - }, - [&]()->std::string { - for (auto& p : i->GetParameters().GetParams()) { - if (p->GetParameterType().GetDirection() == - ParameterType::Direction::IN && - p->GetParameterType().GetBaseType().ToString() == "file") { - return ReplaceAll(CB_PRIVATE_SHARING_BLOCK, "##", - p->GetID()); - } - - if ((p->GetParameterType().GetBaseType().ToString() == "list" || - p->GetParameterType().GetBaseType().ToString() == "array") && - p->GetParameterType().GetBaseType().GetMetaType()->ToString() == "file") { - if (p->GetParameterType().GetBaseType().ToString() == "array") { - - return ReplaceAll(CB_ARRAY_PRIVATE_SHARING_BLOCK, "##", - p->GetID()); - } else { - return ReplaceAll(CB_LIST_PRIVATE_SHARING_BLOCK, "##", - p->GetID()); - } - } - } - return ""; - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetMethodWriteString(inf, *i); - }, - [&]()->std::string { - return GetMethodReadString(inf, *i); - })); + std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() + + "_DELEGATE_" + d->GetID(); + std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(), + ::toupper); + std::string member = ReplaceAll(CB_INTERFACE_DELEGATE_TABLE_MEMBER, + "", enum_value); + member = ReplaceAll(member, "", GetHandlePrefix()); + member = ReplaceAll(member, "", inf.GetID()); + member = ReplaceAll(member, "", d->GetID()); + member = RemoveLine(member); + + delegate_handlers += member; } -} -void CProxyBodyGen::GenInterfaceHandleCtor(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_HANDLE_CTOR, "##", - GetInterfaceIdWithNamespace(inf))); -} + if (delegate_handlers.empty()) + return; -void CProxyBodyGen::GenInterfaceHandleDtor(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_HANDLE_DTOR, "##", - GetInterfaceIdWithNamespace(inf))); -} + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_TABLE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", delegate_handlers); -void CProxyBodyGen::GenInterfaceCtor(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_CTOR, "##", - GetInterfaceIdWithNamespace(inf))); + stream << SmartIndent(code); } -void CProxyBodyGen::GenInterfaceConnect(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_CONNECT, "##", - GetInterfaceIdWithNamespace(inf))); +// @see #CB_INTERFACE_METHOD_ENUM_BASE +void CProxyBodyGen::GenInterfaceMethodEnumBase(std::ofstream& stream, + const Interface& inf) { + std::string enums; + enums += GetHandlePrefix() + "_" + inf.GetID() + "_METHOD_RESULT_,"; + enums += NLine(1); + enums += GetHandlePrefix() + "_" + inf.GetID() + "_METHOD_CALLBACK_,"; + enums += NLine(1); + + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() + + "_METHOD_" + d->GetID() + ","; + enums += enum_value; + enums += NLine(1); + } + + std::transform(enums.begin(), enums.end(), enums.begin(), ::toupper); + std::string code = ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, "", + enums); + code = ReplaceAll(code, "", GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + + stream << SmartIndent(code); } -void CProxyBodyGen::GenInterfaceDtor(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_DTOR, "##", - GetInterfaceIdWithNamespace(inf))); +std::string CProxyBodyGen::GenMethodParams(const Interface& inf, + const Declaration& decl) { + std::string params; + for (auto& p : decl.GetParameters().GetParams()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, inf) + + p->GetID(); + } + + return params; } -void CProxyBodyGen::GenInterfaceConnectSync(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_CONNECT_SYNC, "##", - GetInterfaceIdWithNamespace(inf))); +std::string CProxyBodyGen::GenMethodParamsCheck(const Interface& inf, + const Declaration& decl) { + std::string params_check; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array" || + type.ToString() == "bundle" || + type.ToString() == "string" || + type.ToString() == "file") + params_check += " || " + p->GetID() + " == nullptr"; + } + + return params_check; } -std::string CProxyBodyGen::GetMethodWriteString(const Interface& inf, - const Declaration& decl) { - const char setter[] = "$$($$, $$);\n"; - const char ternary_operation[] = "## ? ## : \"\""; - std::string str; +// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_LIST_FILE_SET_PRIVATE_SHARING +// @see #CB_INTERFACE_METHOD_ARRAY_FILE_SET_PRIVATE_SHARING +// @see #CB_INTERFACE_METHOD_FILE_SET_PRIVATE_SHARING +std::string CProxyBodyGen::GenMethodParcelWrite(const Interface& inf, + const Declaration& decl) { + std::string code; for (auto& p : decl.GetParameters().GetParams()) { - if (p->GetParameterType().GetDirection() == ParameterType::Direction::OUT) + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) continue; - if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) { - str += GenTemplateString(ReplaceAll(CB_DELEGATE_BLOCK, "##", - GetInterfaceIdWithNamespace(inf) + "_" + p->GetParameterType() - .GetBaseType().ToString()), - [&]()->std::string { - return p->GetID(); - }); + + std::string parcel_write_code; + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "", + p->GetID()); + std::string name = GetFullNameFromType(type, inf); + parcel_write_code += GetPrivateSharingString(type, inf, "h->port", + p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "string") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", p->GetID()); + parcel_write_code += GetPrivateSharingString(type, inf, "h->port", + p->GetID()); } else { - str += GenTemplateString(setter, - [&]()->std::string { - return GetParcelWriteFunctionString( - p->GetParameterType().GetBaseType(), true); - }, - [&]()->std::string { - return "parcel"; - }, - [&]()->std::string { - if (p->GetParameterType().GetBaseType().IsUserDefinedType() || - p->GetParameterType().GetBaseType().ToString() == "list" || - p->GetParameterType().GetBaseType().ToString() == "array") { - if (p->GetParameterType().GetDirection() - == ParameterType::Direction::REF) - return "&(*" + p->GetID() + ")->parcelable, " + "*" - + p->GetID(); - else - return "&" + p->GetID() + "->parcelable, " + p->GetID(); - } else if (p->GetParameterType().GetDirection() - == ParameterType::Direction::REF) { - if (p->GetParameterType().GetBaseType().ToString() == "string" - || p->GetParameterType().GetBaseType().ToString() == "file") - return ReplaceAll(ternary_operation, "##", "*" + p->GetID()); - return "*" + p->GetID(); - } else if (p->GetParameterType().GetBaseType().ToString() == "string" - || p->GetParameterType().GetBaseType().ToString() == "file") { - return ReplaceAll(ternary_operation, "##", p->GetID()); - } - return p->GetID(); - }); + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE, + "", GetParcelType(type)); + parcel_write_code = ReplaceAll(parcel_write_code, "", + p->GetID()); } + + code += parcel_write_code; } - return str; + + return RemoveLine(code); } -std::string CProxyBodyGen::GetMethodReadString(const Interface& inf, - const Declaration& decl) { - const char setter[] = "$$($$, $$);\n"; - std::string str; - if (decl.GetMethodType() != Declaration::MethodType::SYNC) { - str += "set_last_result(r);" + NLine(1); - return str; +// @see #CB_INTERFACE_METHOD_DELEGATE_APPEND +std::string CProxyBodyGen::GenMethodDelegateAppend(const Interface& inf, + const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type)) { + std::string delegate_append_code = ReplaceAll( + CB_INTERFACE_METHOD_DELEGATE_APPEND, "", p->GetID()); + code += delegate_append_code; + } } - str += GenTemplateString(CB_RECEIVE_BLOCK, - [&]()->std::string { - std::string s; - for (auto& p : decl.GetParameters().GetParams()) { - if (p->GetParameterType().GetDirection() != - ParameterType::Direction::OUT) - continue; - s += GetReturnTypeString(p->GetParameterType().GetBaseType()) + - "out_" + p->GetID() + ";" + NLine(1); - } - return s; - }, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - std::string s; - for (auto& p : decl.GetParameters().GetParams()) { - if (p->GetParameterType().GetDirection() != - ParameterType::Direction::OUT) - continue; - if (p->GetParameterType().GetBaseType().IsUserDefinedType() || - p->GetParameterType().GetBaseType().ToString() == "list" || - p->GetParameterType().GetBaseType().ToString() == "array") { - s += GetConstructorString(p->GetParameterType().GetBaseType(), - "out_" + p->GetID()); - } - s += GenTemplateString(setter, - [&]()->std::string { - return GetParcelReadFunctionString( - p->GetParameterType().GetBaseType(), true); - }, - [&]()->std::string { - return "parcel_received"; - }, - [&]()->std::string { - auto& t = p->GetParameterType().GetBaseType(); - if (t.IsUserDefinedType() || t.ToString() == "list" || - t.ToString() == "array") { - return "&out_" + p->GetID() + "->parcelable, out_" - + p->GetID(); - } - - return "&out_" + p->GetID(); - }); - s += "*" + p->GetID() + " = out_" + p->GetID() + ";" + NLine(1); - } - if (GetReturnTypeString(decl.GetType()) != "void ") { - if (decl.GetType().IsUserDefinedType() || - decl.GetType().ToString() == "list" || - decl.GetType().ToString() == "array") { - s += GetConstructorString(decl.GetType(), "ret"); - } - s += GenTemplateString(setter, - [&]()->std::string { - return GetParcelReadFunctionString(decl.GetType(), false); - }, - [&]()->std::string { - return "parcel_received"; - }, - [&]()->std::string { - if (decl.GetType().IsUserDefinedType() || - decl.GetType().ToString() == "list" || - decl.GetType().ToString() == "array") - return "&ret->parcelable, ret"; - return "&ret"; - }); - } - return s; - }); - if (GetReturnTypeString(decl.GetType()) != "void ") { - str += "set_last_result(r);" + NLine(1); - str += NLine(1); - str += "return ret;"; + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_ASYNC_BASE +std::string CProxyBodyGen::GenMethodAsyncBase(const Interface& inf, + const Declaration& decl) { + std::string prefix = GetHandlePrefix(); + std::string code = ReplaceAll(CB_INTERFACE_METHOD_ASYNC_BASE, "", + prefix); + std::string name = inf.GetID(); + code = ReplaceAll(code, "", name); + std::string method_name = decl.GetID(); + code = ReplaceAll(code, "", method_name); + std::string args = GenMethodParams(inf, decl); + code = ReplaceAll(code, "", args); + std::string args_check = GenMethodParamsCheck(inf, decl); + code = ReplaceAll(code, "", args_check); + std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper); + code = ReplaceAll(code, "", prefix); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + code = ReplaceAll(code, "", name); + std::transform(method_name.begin(), method_name.end(), method_name.begin(), + ::toupper); + code = ReplaceAll(code, "", method_name); + std::string parcel_write = GenMethodParcelWrite(inf, decl); + code = ReplaceAll(code, "", parcel_write); + std::string delegate_append = GenMethodDelegateAppend(inf, decl); + code = ReplaceAll(code, "", delegate_append); + return code; +} + +std::string CProxyBodyGen::GenMethodArgs(const Interface& inf, + const Declaration& decl) { + std::string args_code; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::OUT) + continue; + + auto& type = param_type.GetBaseType(); + args_code += GetReturnTypeString(type) + "new_" + p->GetID() + ";"; + args_code += NLine(1); } - return str; + + return args_code; +} + +// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_READ +std::string CProxyBodyGen::GenMethodParcelReadBase(const Interface& inf, + const BaseType& type, const std::string& param_name) { + std::string parcel_read_code; + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_read_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + std::string name = GetFullNameFromType(type, inf); + parcel_read_code = ReplaceAll(parcel_read_code, "", name); + parcel_read_code = ReplaceAll(parcel_read_code, "", param_name); + } else if (type.ToString() == "bundle") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ, + "", param_name); + } else if (type.ToString() == "string" || type.ToString() == "file") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ, + "", param_name); + } else { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ, + "", GetParcelType(type)); + parcel_read_code = ReplaceAll(parcel_read_code, "", + param_name); + } + + return parcel_read_code; +} + +// @see #CB_INTERFACE_METHOD_VALUE_SET +std::string CProxyBodyGen::GenMethodParcelRead(const Interface& inf, + const Declaration& decl) { + std::string code; + std::string parcel_read_code; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::OUT) + continue; + + auto& type = param_type.GetBaseType(); + code += GenMethodParcelReadBase(inf, type, "new_" + p->GetID()); + code += ReplaceAll(CB_INTERFACE_METHOD_PARAM_SET, "", + p->GetID()); + } + + // Return Value + auto& base_type = decl.GetType(); + code += GenMethodParcelReadBase(inf, base_type, "ret_"); + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_BASE +std::string CProxyBodyGen::GenMethodBase(const Interface& inf, + const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_BASE, "", + GetReturnTypeString(decl.GetType())); + std::string prefix = GetHandlePrefix(); + code = ReplaceAll(code, "", prefix); + std::string name = inf.GetID(); + code = ReplaceAll(code, "", name); + std::string method_name = decl.GetID(); + code = ReplaceAll(code, "", method_name); + std::string args = GenMethodParams(inf, decl); + code = ReplaceAll(code, "", args); + std::string values = GenMethodArgs(inf, decl); + code = ReplaceAll(code, "", values); + std::string error_value = GetErrorValue(decl.GetType()); + code = ReplaceAll(code, "", error_value); + std::string args_check = GenMethodParamsCheck(inf, decl); + code = ReplaceAll(code, "", args_check); + std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper); + code = ReplaceAll(code, "", prefix); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + code = ReplaceAll(code, "", name); + std::transform(method_name.begin(), method_name.end(), method_name.begin(), + ::toupper); + code = ReplaceAll(code, "", method_name); + std::string parcel_write = GenMethodParcelWrite(inf, decl); + code = ReplaceAll(code, "", parcel_write); + std::string parcel_read = GenMethodParcelRead(inf, decl); + code = ReplaceAll(code, "", parcel_read); + std::string delegate_append = GenMethodDelegateAppend(inf, decl); + code = ReplaceAll(code, "", delegate_append); + return code; +} + +void CProxyBodyGen::GenInterfaceMethodBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code; + auto method_type = decl.GetMethodType(); + if (method_type == Declaration::MethodType::ASYNC) + code = GenMethodAsyncBase(inf, decl); + else + code = GenMethodBase(inf, decl); + + stream << SmartIndent(code); } } // namespace tidl diff --git a/idlc/gen/c_proxy_body_gen.h b/idlc/gen/c_proxy_body_gen.h index a89c6020..e523f245 100644 --- a/idlc/gen/c_proxy_body_gen.h +++ b/idlc/gen/c_proxy_body_gen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,77 +21,66 @@ #include #include "idlc/gen/c_body_gen_base.h" +#include "idlc/options.h" namespace tidl { class CProxyBodyGen : public CBodyGeneratorBase { public: - explicit CProxyBodyGen(std::shared_ptr doc); + explicit CProxyBodyGen(std::shared_ptr doc, + std::shared_ptr options); virtual ~CProxyBodyGen() = default; void OnInitGen(std::ofstream& stream) override; void OnFiniGen(std::ofstream& stream) override; private: - void GenTypedefProxyDelegate(std::ofstream& stream); - void GenInterfaces(std::ofstream& stream); + void GenInterfaceDefs(std::ofstream& stream); + void GenInterfaceDef(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateDef(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + void GenInterfaceBaseDef(std::ofstream& stream, const Interface& inf); - private: + void GenInterfaces(std::ofstream& stream); + void GenInterfaceDelegateCallback(std::ofstream& stream); void GenInterface(std::ofstream& stream, const Interface& inf); - void GenInterfaceFileSharing(std::ofstream& stream, const Interface& st); - void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf); - void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf); - void GenInterfaceDelegatorTable(std::ofstream& stream, const Interface& inf); - void GenInterfaceDelegatorHandler(std::ofstream& stream, - const Interface& inf); - void GenInterfaceConsumeCommand(std::ofstream& stream, - const Interface& inf); - void GenInterfaceOnConnectedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceOnDisconnectedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceOnRejectedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceOnReceivedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceMethods(std::ofstream& stream, const Interface& inf); - void GenInterfaceHandleCtor(std::ofstream& stream, const Interface& inf); - void GenInterfaceHandleDtor(std::ofstream& stream, const Interface& inf); - void GenInterfaceCtor(std::ofstream& stream, const Interface& inf); - void GenInterfaceConnect(std::ofstream& stream, const Interface& inf); - void GenInterfaceDtor(std::ofstream& stream, const Interface& inf); - void GenInterfaceConnectSync(std::ofstream& stream, const Interface& inf); + void GenInterfaceBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateEnumBase(std::ofstream& stream, + const Interface& inf); + void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + void GenInterfaceDelegateTable(std::ofstream& stream, const Interface& inf); + void GenInterfaceMethodEnumBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceMethodBase(std::ofstream& stream, const Interface& inf, + const Declaration& decl); - private: - void GenInterfaceDelegator(std::ofstream& stream, const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDeclaration(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorSerializer(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDeserializer(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorConstructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDisposer(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorInvoker(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDestructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl); + bool HasListFile(const Interface& inf); - private: - std::string GetMethodWriteString(const Interface& inf, - const Declaration& decl); - std::string GetMethodReadString(const Interface& inf, - const Declaration& decl); + std::string GenDelegateArgsDecl(const Interface& inf, + const Declaration& decl); + std::string GenDelegateParcelRead(const Interface& inf, + const Declaration& decl); + std::string GenDelegateArgsFree(const Interface& inf, + const Declaration& decl); + std::string GenDelegateCallbackArgs(const Declaration& decl); + + std::string GenMethodAsyncBase(const Interface& inf, const Declaration& decl); + std::string GenMethodBase(const Interface& inf, const Declaration& decl); + std::string GenMethodParams(const Interface& inf, const Declaration& decl); + std::string GenMethodParamsCheck(const Interface& inf, + const Declaration& decl); + std::string GenMethodParcelWrite(const Interface& inf, + const Declaration& decl); + std::string GenMethodDelegateAppend(const Interface& inf, + const Declaration& decl); + std::string GenMethodArgs(const Interface& inf, const Declaration& decl); + std::string GenMethodParcelReadBase(const Interface& inf, + const BaseType& type, const std::string& param_name); + std::string GenMethodParcelRead(const Interface& inf, + const Declaration& decl); + + private: + std::shared_ptr options_; }; } // namespace tidl diff --git a/idlc/gen/c_proxy_body_gen_cb.h b/idlc/gen/c_proxy_body_gen_cb.h index 0757b2d9..54885ea4 100644 --- a/idlc/gen/c_proxy_body_gen_cb.h +++ b/idlc/gen/c_proxy_body_gen_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,568 +17,929 @@ #ifndef IDLC_C_GEN_C_PROXY_BODY_GEN_CB_H_ #define IDLC_C_GEN_C_PROXY_BODY_GEN_CB_H_ -const char CB_INTERFACE_STRUCT[] = +constexpr const char CB_INTERFACE_DELEGATE_CALLBACK[] = R"__c_cb( -struct ##_s { - char *stub_appid; - rpc_port_proxy_h proxy; - rpc_port_h port; - rpc_port_h callback_port; - rpc_port_proxy_##_callback_s callback; - void *user_data; - GList *delegates; - GRecMutex mutex; -}; +typedef void (*rpc_port_proxy_delegate_cb)(GList **delegates, rpc_port_parcel_h parcel, int id, int seq_id); )__c_cb"; -const char CB_FILE_LIST_SHARING[] = +/** + * The enumeration of the interface delegate. + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_ENUM_BASE[] = R"__c_cb( -int __file_list_set_private_sharing(rpc_port_h port, GList *list_files) { - const char **arr = calloc(g_list_length(list_files), sizeof(char*)); - GList *iter; - int idx = 0; - int r = 0; - iter = list_files; - while (iter) { - char *value = iter->data; - if (!value) { - _W("Warning: value is NULL"); - continue; - } - arr[idx++] = value; - iter = g_list_next(iter); - } - if (idx > 0) - r = rpc_port_set_private_sharing_array(port, arr, idx); - return r; -} +typedef enum { + +} __delegate_e; )__c_cb"; -const char CB_FILE_ARRAY_SHARING[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_DEF[] = R"__c_cb( -int __file_array_set_private_sharing(rpc_port_h port, - const char **files, int files_size) { - return rpc_port_set_private_sharing_array(port, files, files_size); -} +typedef struct ___s { + rpc_port_parcelable_t parcelable; + int id; + int seq_id; + bool once; + ___cb callback; + void *user_data; +} ___t; )__c_cb"; -const char CB_DELEGATE_STRUCT[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + * The enumeration value of the delegate. + * The implementation to declares the arguments. + * The implementation to read the arguments from the parcel. + * The implementation to release the allocated arguments. + * The arguments of the delegate callback. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE[] = R"__c_cb( -struct ##_s { - rpc_port_parcelable_t parcelable; - int id; - int seq_id; - ## callback; - bool once; - void *user_data; -}; -)__c_cb"; +static void _____to(rpc_port_parcel_h parcel, void *data) +{ + ___h h = data; -const char CB_DELEGATE_SERIALIZER[] = -R"__c_cb( -static void __##_to(rpc_port_parcel_h parcel, void *data) + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + return; + } + + rpc_port_parcel_write_int32(parcel, h->id); + + rpc_port_parcel_write_int32(parcel, h->seq_id); + + rpc_port_parcel_write_bool(parcel, h->once); + + _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); +} + +static void _____from(rpc_port_parcel_h parcel, void *data) { - struct ##_s *handle = data; + ___h h = data; - if (!handle) { - _E("Invalid parameter"); - return; - } + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } - rpc_port_parcel_write_int32(parcel, handle->id); - rpc_port_parcel_write_int32(parcel, handle->seq_id); - rpc_port_parcel_write_bool(parcel, handle->once); - _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false"); + rpc_port_parcel_read_int32(parcel, &h->id); + + rpc_port_parcel_read_int32(parcel, &h->seq_id); + + rpc_port_parcel_read_bool(parcel, &h->once); + + _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); + set_last_result(RPC_PORT_ERROR_NONE); } -)__c_cb"; -const char CB_DELEGATE_DESERIALIZER[] = -R"__c_cb( -static void __##_from(rpc_port_parcel_h parcel, void *data) +int ___create(___h *h) { - struct ##_s *handle = data; + ___t *handle; + static int seq_num; - if (!handle) { - _E("Invalid parameter"); - return; - } + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + handle = calloc(1, sizeof(___t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + handle->parcelable.to = _____to; + handle->parcelable.from = _____from; + handle->id = ; + handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1; + _I("id(%d), seq_id(%d)", handle->id, handle->seq_id); - rpc_port_parcel_read_int32(parcel, &handle->id); - rpc_port_parcel_read_int32(parcel, &handle->seq_id); - rpc_port_parcel_read_bool(parcel, &handle->once); - _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false"); + *h = handle; + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_DELEGATE_CTOR[] = -R"__c_cb( -rpc_port_##_h rpc_port_##_create(## callback, bool once, void *user_data) +int ___destroy(___h h) { - struct ##_s *handle; - static int seq_num; + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - handle = calloc(1, sizeof(struct ##_s)); - if (!handle) { - _E("Out of memory"); - return NULL; - } + _W("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); - handle->parcelable.to = __##_to; - handle->parcelable.from= __##_from; - handle->id = $$_DELEGATE_$$; - handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1; - handle->callback = callback; - handle->once = once; - handle->user_data = user_data; - _I("id(%d), seq_id(%d)", handle->id, handle->seq_id); + free(h); - return handle; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_DELEGATE_DISPOSER[] = -R"__c_cb( -int rpc_port_proxy_##_dispose(rpc_port_proxy_$$_h proxy, rpc_port_##_h delegate) +int ___clone(___h h, ___h *clone) { - struct ##_s *handle; - GList *iter; + ___h handle; + rpc_port_parcel_h parcel; + int ret; + + if (h == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret = ___create(&handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + return ret; + } + + ret = rpc_port_parcel_create(&parcel); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret); + ___destroy(handle); + return ret; + } + + rpc_port_parcel_write(parcel, &h->parcelable, h); + rpc_port_parcel_read(parcel, &handle->parcelable, handle); + ret = get_last_result(); + rpc_port_parcel_destroy(parcel); + + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", ret); + ___destroy(handle); + return ret; + } + + *clone = handle; + + return RPC_PORT_ERROR_NONE; +} - if (!proxy || !delegate) { - _E("Invalid handle %p %p", proxy, delegate); - return -1; - } +int ___set_callback(___h h, ___cb callback, void *user_data) +{ + if (h == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - iter = proxy->delegates; - while (iter) { - handle = (struct ##_s *)iter->data; - if (handle == delegate) { - _W("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false"); - proxy->delegates = g_list_remove_link(proxy->delegates, iter); - free(handle); - g_list_free(iter); - return 0; - } - iter = g_list_next(iter); - } + h->callback = callback; + h->user_data = user_data; - return -1; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_DELEGATE_DTOR[] = -R"__c_cb( -int rpc_port_##_destroy(rpc_port_##_h delegate) +int ___set_once(___h h, bool once) { - if (!delegate) { - _E("Invalid parameter"); - return -1; - } + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - free(delegate); + h->once = once; - return 0; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_DELEGATE_INVOKER[] = -R"__c_cb( -static void __$$_delegate_$$(GList **list, rpc_port_parcel_h parcel, int seq_id, int id) +int ___get_id(___h h, int *id) { -$$ - do { - struct ##_s *handle; - GList *iter; - - iter = *list; - while (iter) { - handle = (struct ##_s *)iter->data; - if (handle->seq_id == seq_id && handle->id == id) { - bool once = handle->once; - - _W("Invoke id(%d), seq_id(%d)", id, seq_id); - $$ - if (once) { - _W("Dispose"); - *list = g_list_remove_link(*list, iter); - free(handle); - g_list_free(iter); - } - break; - } - iter = g_list_next(iter); - } - } while (0); -$$ + if (h == nullptr || id == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *id = h->id; + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_PROCESS_RECEIVED_EVENT[] = -R"__c_cb( -static void __##_process_received_event(GList **list, rpc_port_parcel_h parcel) +int ___get_seq_id(___h h, int *seq_id) { -$$ + if (h == nullptr || seq_id == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *seq_id = h->seq_id; + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_PROCESS_RECEIVED_EVENT_IMPL[] = -R"__c_cb(int id; -int seq_id; -bool once; +int ___is_once(___h h, bool *once) +{ + if (h == nullptr || once == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } -rpc_port_parcel_read_int32(parcel, &id); -rpc_port_parcel_read_int32(parcel, &seq_id); -rpc_port_parcel_read_bool(parcel, &once); -_W("id(%d), seq_id(%d)", id, seq_id); + *once = h->once; -if (id > 0 && id < (sizeof(__##_delegate_table) / sizeof(__##_delegate_table[0]))) { - if (__##_delegate_table[id]) - __##_delegate_table[id](list, parcel, seq_id, id); -} else { - _W("Unknown id(%d)", id); -})__c_cb"; + return RPC_PORT_ERROR_NONE; +} -const char CB_CONSUME_COMMAND[] = -R"__c_cb( -static rpc_port_parcel_h __##_consume_command(rpc_port_proxy_##_h h) +int ___get_tag(___h h, char **tag) { - rpc_port_parcel_h parcel = NULL; - int cmd = -1; + char *new_tag; + char buf[128]; - do { - rpc_port_parcel_create_from_port(&parcel, h->port); - if (!parcel) - break; + if (h == nullptr || tag == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - rpc_port_parcel_read_int32(parcel, &cmd); - if (cmd == ##_METHOD_Result) - return parcel; + snprintf(buf, sizeof(buf), "%d::%d", h->id, h->seq_id); + new_tag = strdup(buf); + if (new_tag == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } - rpc_port_parcel_destroy(parcel); - parcel = NULL; - } while (true); + *tag = new_tag; - return NULL; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_ON_CONNECTED[] = -R"__c_cb( -static void __##_on_connected(const char *endpoint, const char *port_name, rpc_port_h port, void *data) +int ___dispose(__h proxy, ___h h) +{ + GList *found; + + if (proxy == nullptr || h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + found = g_list_find(proxy->delegates, h); + if (found == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + proxy->delegates = g_list_remove_link(proxy->delegates, found); + ___destroy(h); + g_list_free(found); + + return RPC_PORT_ERROR_NONE; +} + +static void _____delegate_handler(GList **delegates, rpc_port_parcel_h parcel, int id, int seq_id) { - rpc_port_proxy_##_h handle = data; + ___h handle; + GList *iter; + bool once; + + + + + iter = *delegates; + while (iter) { + handle = iter->data; + iter = g_list_next(iter); + if (handle->id == id && handle->seq_id == seq_id) { + once = handle->once; + _W("Invoke id(%d), seq_id(%d)", id, seq_id); + if (handle->callback) + handle->callback(handle->user_data); + else + _W("The callback function is nullptr"); + + if (once) { + *delegates = g_list_remove(*delegates, handle); + ___destroy(handle); + } + + break; + } + } - handle->port = port; - rpc_port_proxy_get_port(handle->proxy, RPC_PORT_PORT_CALLBACK, &handle->callback_port); - if (handle->callback.connected) - handle->callback.connected(handle, handle->user_data); - _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name); +out: + } )__c_cb"; -const char CB_ON_DISCONNECTED[] = +/** + * The prefix of the structure. + * The name of the structure. + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_READ[] = R"__c_cb( -static void __##_on_disconnected(const char *endpoint, const char *port_name, void *data) -{ - rpc_port_proxy_##_h handle = data; +__create(&); +if ( == nullptr) { + _E("Failed to create handle"); + goto out; +} - handle->port = NULL; - if (handle->callback.disconnected) - handle->callback.disconnected(handle, handle->user_data); - _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name); +rpc_port_parcel_read(parcel, &->parcelable, ); +if (get_last_result() != RPC_PORT_ERROR_NONE) { + _E("Failed to read data"); + goto out; } )__c_cb"; -const char CB_ON_REJECTED[] = +/** + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_READ[] = R"__c_cb( -static void __##_on_rejected(const char *endpoint, const char *port_name, void *data) -{ - rpc_port_proxy_##_h handle = data; +rpc_port_parcel_read_bundle(parcel, &); +if ( == nullptr) { + _E("Failed to read data"); + goto out; +} +)__c_cb"; - handle->port = NULL; - if (handle->callback.rejected) - handle->callback.rejected(handle, handle->user_data); - _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name); +/** + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_STRING_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_string(parcel, &); +if ( == nullptr) { + _E("Failed to read data"); + goto out; } )__c_cb"; -const char CB_ON_RECEIVED[] = +/** + * The type of the parcel. + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE_PARCEL_READ[] = R"__c_cb( -static void __##_on_received(const char *endpoint, const char *port_name, void *data) -{ - rpc_port_proxy_##_h handle = data; - rpc_port_parcel_h parcel_received = NULL; - int cmd = -1; - - rpc_port_parcel_create_from_port(&parcel_received, handle->callback_port); - if (!parcel_received) { - _E("Failed to create parcel from port(%s)", port_name); - return; - } +rpc_port_parcel_read_(parcel, &); +)__c_cb"; - rpc_port_parcel_read_int32(parcel_received, &cmd); - if (cmd != ##_METHOD_Callback) { - _E("Invalid protocol"); - rpc_port_parcel_destroy(parcel_received); - return; - } +/** + * The prefix of the structure. + * The name of the structure. + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_USER_DEFINED_ARG_FREE[] = +R"__c_cb( +if () + __destroy(); +)__c_cb"; - __##_process_received_event(&handle->delegates, parcel_received); - rpc_port_parcel_destroy(parcel_received); - _I("[__RPC_PORT__] endpoint(%s), port_name(%s)", endpoint, port_name); -} +/** + * The name of the value. + */ +constexpr const char CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE[] = +R"__c_cb( +if () + bundle_free(); )__c_cb"; -const char CB_INTERFACE_METHODS[] = +/** + * The name of the value; + */ +constexpr const char CB_INTERFACE_DELEGATE_STRING_ARG_FREE[] = R"__c_cb( -$$rpc_port_proxy_##_invoke_$$(rpc_port_proxy_##_h h$$) -{ - rpc_port_parcel_h parcel; - int r; -$$ +if () + free(); +)__c_cb"; - if (!h$$) { - _E("Invalid parameter"); - return$$; - } +/** + * The prefix of the interface. + * The name of the interface. + * The array of the delegate callbacks. + */ +constexpr const char CB_INTERFACE_DELEGATE_TABLE[] = +R"__c_cb( +static _delegate_cb ____delegate_table[] = { + +}; +)__c_cb"; - if (!h->port) { - _E("Not connected"); - return$$; - } -$$ - rpc_port_parcel_create(&parcel); - rpc_port_parcel_write_int32(parcel, ##_METHOD_$$); -$$ - r = rpc_port_parcel_send(parcel, h->port); - if (r != RPC_PORT_ERROR_NONE) { - _E("Failed to send parcel. result(%d)", r); - r = RPC_PORT_ERROR_IO_ERROR; - } +/** + * The enumeration value. + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_TABLE_MEMBER[] = +R"__c_cb( +[] = _____delegate_handler, +)__c_cb"; - rpc_port_parcel_destroy(parcel); -$$ -} +/** + * The enumerations of the interface method. + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_ENUM_BASE[] = +R"__c_cb( +typedef enum { + +} __method_e; )__c_cb"; -const char CB_INTERFACE_HANDLE_CTOR[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_BASE_DEF[] = R"__c_cb( -static struct ##_s *__create_##(const char *stub_appid, rpc_port_proxy_##_callback_s *callback, void *user_data) -{ - struct ##_s *handle; +typedef struct __s { + char *stub_appid; + rpc_port_proxy_h proxy; + rpc_port_h port; + rpc_port_h callback_port; + __callback_s callback; + void *user_data; + GList *delegates; + GRecMutex mutex; +} __t; +)__c_cb"; - handle = calloc(1, sizeof(struct ##_s)); - if (!handle) { - _E("Out of memory"); - return NULL; - } +/** + * The prefix of the interface. + * The name of the interface. + * The uppercase prefix of the interface. + * The uppercase name of the interface. + */ +constexpr const char CB_INTERFACE_BASE[] = +R"__c_cb( +static void ____process_received_event(GList **delegates, rpc_port_parcel_h parcel) +{ + int id = 0; + int seq_id = 0; + bool once = false; + + rpc_port_parcel_read_int32(parcel, &id); + rpc_port_parcel_read_int32(parcel, &seq_id); + rpc_port_parcel_read_bool(parcel, &once); + _W("id(%d), seq_id(%d)", id, seq_id); + + if (id > 0 && id < ARRAY_SIZE(____delegate_table)) { + if (____delegate_table[id]) + ____delegate_table[id](delegates, parcel, id, seq_id); + } else { + _W("Unknown ID(%d)", id); + } +} - handle->stub_appid = strdup(stub_appid); - if (!handle->stub_appid) { - _E("Out of memory"); - free(handle); - return NULL; +static void ____consume_command(rpc_port_h port, rpc_port_parcel_h *p) +{ + rpc_port_parcel_h parcel; + int cmd = -1; + int ret; + + do { + ret = rpc_port_parcel_create_from_port(&parcel, port); + if (ret != RPC_PORT_ERROR_NONE) + break; + + rpc_port_parcel_read_int32(parcel, &cmd); + if (cmd == __METHOD_RESULT_) { + *p = parcel; + return; } - rpc_port_proxy_create(&handle->proxy); - if (!handle->proxy) { - _E("Failed to create proxy"); - free(handle->stub_appid); - free(handle); - return NULL; - } + rpc_port_parcel_destroy(parcel); + } while (true); - g_rec_mutex_init(&handle->mutex); + *p = nullptr; +} - handle->callback = *callback; - handle->user_data = user_data; +static void ____connected(const char *endpoint, const char *port_name, rpc_port_h port, void *data) +{ + __h h = data; - return handle; + _I("endpoint(%s), port_name(%s)", endpoint, port_name); + h->port = port; + rpc_port_proxy_get_port(h->proxy, RPC_PORT_PORT_CALLBACK, &h->callback_port); + h->callback.connected(h, h->user_data); } -)__c_cb"; -const char CB_INTERFACE_HANDLE_DTOR[] = -R"__c_cb( -static void __destroy_##(struct ##_s *h) +static void ____disconnected(const char *endpoint, const char *port_name, void *data) { - if (!h) - return; + __h h = data; - g_rec_mutex_clear(&h->mutex); + _W("endpoint(%s), port_name(%s)", endpoint, port_name); + h->port = nullptr; + h->callback.disconnected(h, h->user_data); - if (h->delegates) - g_list_free_full(h->delegates, free); +} - if (h->proxy) - rpc_port_proxy_destroy(h->proxy); +static void ____rejected(const char *endpoint, const char *port_name, void *data) +{ + __h h = data; - if (h->stub_appid) - free(h->stub_appid); + _W("endpoint(%s), port_name(%s)", endpoint, port_name); + h->port = nullptr; + h->callback.rejected(h, h->user_data); +} - free(h); +static void ____received(const char *endpoint, const char *port_name, void *data) +{ + __h h = data; + rpc_port_parcel_h parcel; + int cmd = -1; + int ret; + + _W("endpoint(%s), port_name(%s)", endpoint, port_name); + ret = rpc_port_parcel_create_from_port(&parcel, h->callback_port); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle from port. error(%d)", ret); + return; + } + + rpc_port_parcel_read_int32(parcel, &cmd); + if (cmd != __METHOD_CALLBACK_) { + _E("Invalid protocol"); + rpc_port_parcel_destroy(parcel); + return; + } + + ____process_received_event(&h->delegates, parcel); + rpc_port_parcel_destroy(parcel); } -)__c_cb"; -const char CB_INTERFACE_CTOR[] = -R"__c_cb( -int rpc_port_proxy_##_create(const char *stub_appid, rpc_port_proxy_##_callback_s *callback, void *user_data, rpc_port_proxy_##_h *h) +int __create(const char *stub_appid, __callback_s *callback, void *user_data, __h *h) +{ + __t *handle; + int ret; + + if (stub_appid == nullptr || callback == nullptr || h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + if (callback->connected == nullptr || callback->disconnected == nullptr || callback->rejected == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + handle = calloc(1, sizeof(__t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + g_rec_mutex_init(&handle->mutex); + + handle->stub_appid = strdup(stub_appid); + if (handle->stub_appid == nullptr) { + _E("Failed to duplicate stub appid"); + __destroy(handle); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + ret = rpc_port_proxy_create(&handle->proxy); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create proxy handle. error(%d)", ret); + __destroy(handle); + return ret; + } + + handle->callback = *callback; + handle->user_data = user_data; + + ret = rpc_port_proxy_add_connected_event_cb(handle->proxy, ____connected, handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add connected event cb. error(%d)", ret); + __destroy(handle); + return ret; + } + + ret = rpc_port_proxy_add_disconnected_event_cb(handle->proxy, ____disconnected, handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add disconnected event cb. error(%d)", ret); + __destroy(handle); + return ret; + } + + ret = rpc_port_proxy_add_rejected_event_cb(handle->proxy, ____rejected, handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add rejected event cb. error(%d)", ret); + __destroy(handle); + return ret; + } + + ret = rpc_port_proxy_add_received_event_cb(handle->proxy, ____received, handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add received event cb. error(%d)", ret); + __destroy(handle); + return ret; + } + + *h = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __destroy(__h h) { - struct ##_s *handle; - int r; + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - if (!stub_appid || !callback || !h) { - _E("Invalid parameter"); - return -1; - } + g_rec_mutex_lock(&h->mutex); + g_rec_mutex_unlock(&h->mutex); + g_rec_mutex_clear(&h->mutex); - handle = __create_##(stub_appid, callback, user_data); - if (!handle) - return -1; + if (h->delegates) + g_list_free_full(h->delegates, free); - r = rpc_port_proxy_add_connected_event_cb(handle->proxy, __##_on_connected, handle); - if (r != 0) { - _E("Failed to add connected event cb. err = %d", r); - __destroy_##(handle); - return r; - } + if (h->proxy) + rpc_port_proxy_destroy(h->proxy); - r = rpc_port_proxy_add_disconnected_event_cb(handle->proxy, __##_on_disconnected, handle); - if (r != 0) { - _E("Failed to add disconnected event cb. err = %d", r); - __destroy_##(handle); - return r; - } + if (h->stub_appid) + free(h->stub_appid); - r = rpc_port_proxy_add_rejected_event_cb(handle->proxy, __##_on_rejected, handle); - if (r != 0) { - _E("Failed to add rejected event cb. err = %d", r); - __destroy_##(handle); - return r; - } + free(h); - r = rpc_port_proxy_add_received_event_cb(handle->proxy, __##_on_received, handle); - if (r != 0) { - _E("Failed to add received event cb. err = %d", r); - __destroy_##(handle); - return r; - } + return RPC_PORT_ERROR_NONE; +} + +int __connect(__h h) +{ + int ret; + + if (h == nullptr || h->proxy == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - *h = handle; + ret = rpc_port_proxy_connect(h->proxy, h->stub_appid, ""); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to connect to stub. error(%d)", ret); + return ret; + } - return 0; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_CONNECT[] = -R"__c_cb( -int rpc_port_proxy_##_connect(rpc_port_proxy_##_h h) +int __connect_sync(__h h) { - int r; + int ret; - if (!h || !h->proxy) { - _E("Invalid parameter"); - return -1; - } + if (h == nullptr || h->proxy == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - r = rpc_port_proxy_connect(h->proxy, h->stub_appid, "##"); - if (r != 0) { - _E("Failed to connect ##(%s)", h->stub_appid); - return r; - } + ret = rpc_port_proxy_connect_sync(h->proxy, h->stub_appid, ""); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to connect to stub. error(%d)", ret); + return ret; + } - return 0; + return RPC_PORT_ERROR_NONE; } )__c_cb"; -const char CB_INTERFACE_DTOR[] = +/** + * The prefix of the interface. + * The name of the interface. + * The method name of the interface. + * The parameters of the method of the interface + * The parameters check of the method. + * The uppercase prefix of the interface. + * The uppercase name of the interface. + * The uppercase method name of the interface. + * The implementation to write arguments to the parcel. + * The implementation to add the delegates to the list. + */ +constexpr const char CB_INTERFACE_METHOD_ASYNC_BASE[] = +R"__c_cb( +void __invoke_(__h h) +{ + rpc_port_parcel_h parcel_; + int res_; + + if (h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + g_rec_mutex_lock(&h->mutex); + if (h->port == nullptr) { + _E("Not connected"); + g_rec_mutex_unlock(&h->mutex); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + res_ = rpc_port_parcel_create(&parcel_); + if (res_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", res_); + g_rec_mutex_unlock(&h->mutex); + set_last_result(res_); + return; + } + + rpc_port_parcel_write_int32(parcel_, __METHOD_); + + + + + res_ = rpc_port_parcel_send(parcel_, h->port); + rpc_port_parcel_destroy(parcel_); + if (res_ != RPC_PORT_ERROR_NONE) + _E("Failed to send parcel. error(%d)", res_); + + g_rec_mutex_unlock(&h->mutex); + set_last_result(res_); +} +)__c_cb"; + +/** + * The return type of the method of the interface. + * The prefix of the interface. + * The name of the interface. + * The method name of the interface. + * The value declarations for reading the data from the parcel. + * The error value of the method. + * The parameters of the method of the interface. + * The parameters check of the method. + * The uppercase prefix of the interface. + * The uppercase name of the interface. + * The uppercase method name of the interface. + * The implementation to write arguments to the parcel. + * The implementation to read results from the parcel. + * The implementation to add the delegates to the list. + */ +constexpr const char CB_INTERFACE_METHOD_BASE[] = R"__c_cb( -int rpc_port_proxy_##_destroy(rpc_port_proxy_##_h h) +__invoke_(__h h) { - if (!h) { - _E("Invalid parameter"); - return -1; + rpc_port_parcel_h parcel_; + int res_; + ret_ = ; + + + if (h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return ret_; + } + + g_rec_mutex_lock(&h->mutex); + if (h->port == nullptr) { + _E("Not connected"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + g_rec_mutex_unlock(&h->mutex); + return ret_; + } + + res_ = rpc_port_parcel_create(&parcel_); + if (res_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", res_); + set_last_result(res_); + g_rec_mutex_unlock(&h->mutex); + return ret_; + } + + rpc_port_parcel_write_int32(parcel_, __METHOD_); + + + + + res_ = rpc_port_parcel_send(parcel_, h->port); + rpc_port_parcel_destroy(parcel_); + if (res_ != RPC_PORT_ERROR_NONE) { + _E("Failed to send parcel. error(%d)", res_); + set_last_result(res_); + g_rec_mutex_unlock(&h->mutex); + return ret_; + } + + do { + parcel_ = nullptr; + ____consume_command(h->port, &parcel_); + if (parcel_ == nullptr) { + _E("Invalid protocol"); + res_ = RPC_PORT_ERROR_IO_ERROR; + break; } - __destroy_##(h); - return 0; + + rpc_port_parcel_destroy(parcel_); + } while (0); + g_rec_mutex_unlock(&h->mutex); + set_last_result(res_); + + return ret_; } )__c_cb"; -const char CB_DELEGATE_BLOCK[] = +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE[] = R"__c_cb( -do { - struct ##_s *handle = $$; - - rpc_port_parcel_write(parcel, &handle->parcelable, handle); - h->delegates = g_list_append(h->delegates, handle); -} while (0); +rpc_port_parcel_write(parcel_, &->parcelable, ); )__c_cb"; -const char CB_RECEIVE_BLOCK[] = +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE[] = R"__c_cb( -g_rec_mutex_lock(&h->mutex); -do { - rpc_port_parcel_h parcel_received; -$$ - parcel_received = __$$_consume_command(h); - if (!parcel_received) { - _E("Invalid protocol"); - r = RPC_PORT_ERROR_IO_ERROR; - break; - } +rpc_port_parcel_write_bundle(parcel_, ); +)__c_cb"; -$$ - rpc_port_parcel_destroy(parcel_received); -} while (0); -g_rec_mutex_unlock(&h->mutex); +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel_, ); )__c_cb"; -const char CB_LIST_PRIVATE_SHARING_BLOCK[] = +/** + * The type of the parcel. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_WRITE[] = R"__c_cb( - r = __file_list_set_private_sharing(h->port, ##->list_files); - if (r != RPC_PORT_ERROR_NONE) { - _E("Fail to set private sharing"); - return ret; - } +rpc_port_parcel_write_(parcel_, ); )__c_cb"; -const char CB_ARRAY_PRIVATE_SHARING_BLOCK[] = +/** + * The prefix of the structure. + * The name of the structure. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ[] = R"__c_cb( - r = __file_array_set_private_sharing(h->port, - (const char **)##->array_files, ##->array_files_size); - if (r != RPC_PORT_ERROR_NONE) { - _E("Fail to set private sharing"); - return ret; - } + = nullptr; +__create(&); +if ( == nullptr) { + _E("Failed to create handle"); + res_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + break; +} + +rpc_port_parcel_read(parcel_, &->parcelable, ); +if (get_last_result() != RPC_PORT_ERROR_NONE) { + _E("Failed to read data"); + __destroy(); + res_ = get_last_result(); + break; +} )__c_cb"; -const char CB_PRIVATE_SHARING_BLOCK[] = +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ[] = R"__c_cb( - r = rpc_port_set_private_sharing(h->port, ##); - if (r != RPC_PORT_ERROR_NONE) { - _E("Fail to set private sharing"); - return ret; - } + = nullptr; +rpc_port_parcel_read_bundle(parcel_, &); +if ( == nullptr) { + _E("Failed to read data"); + res_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + break; +} )__c_cb"; -const char CB_INTERFACE_CONNECT_SYNC[] = +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] = R"__c_cb( -int rpc_port_proxy_##_connect_sync(rpc_port_proxy_##_h h) -{ - int r; + = nullptr; +rpc_port_parcel_read_string(parcel_, &); +if ( == nullptr) { + _E("Failed to read data"); + res_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + break; +} +)__c_cb"; - if (!h || !h->proxy) { - _E("Invalid parameter"); - return -1; - } +/** + * The type of the parcel. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_(parcel_, &); +)__c_cb"; - r = rpc_port_proxy_connect_sync(h->proxy, h->stub_appid, "##"); - if (r != 0) { - _E("Failed to connect sync ##(%s)", h->stub_appid); - return r; - } +/** + * The name of the parameter. + */ +constexpr const char CB_INTERFACE_METHOD_PARAM_SET[] = +R"__c_cb( +* = new_; +)__c_cb"; - return 0; -} +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_DELEGATE_APPEND[] = +R"__c_cb( +h->delegates = g_list_append(h->delegates, ); )__c_cb"; #endif // IDLC_C_GEN_C_PROXY_BODY_GEN_CB_H_ diff --git a/idlc/gen/c_proxy_header_gen.cc b/idlc/gen/c_proxy_header_gen.cc index b5bca942..4c52398f 100644 --- a/idlc/gen/c_proxy_header_gen.cc +++ b/idlc/gen/c_proxy_header_gen.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,13 +23,16 @@ namespace { namespace tidl { CProxyHeaderGen::CProxyHeaderGen(std::shared_ptr doc) - : CHeaderGeneratorBase(doc) {} + : CHeaderGeneratorBase(doc) { +} void CProxyHeaderGen::OnInitGen(std::ofstream& stream) { GenVersion(stream); GenPragmaOnce(stream); GenIncludeDefaultHeaders(stream, false); GenExplicitLinkageOpen(stream); + GenStructureHandles(stream); + GenInterfaceHandles(stream); GenStructures(stream); GenInterfaces(stream); } @@ -38,6 +41,43 @@ void CProxyHeaderGen::OnFiniGen(std::ofstream& stream) { GenExplicitLinkageClose(stream); } +void CProxyHeaderGen::GenInterfaceHandles(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& inf = static_cast(*b); + GenInterfaceHandle(stream, inf); + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateHandle(stream, inf, *d); + } + } +} + +// @see #CB_INTERFACE_HANDLE +void CProxyHeaderGen::GenInterfaceHandle(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_HANDLE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_DELEGATE_HANDLE +void CProxyHeaderGen::GenInterfaceDelegateHandle(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_HANDLE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + + stream << SmartIndent(code); +} + void CProxyHeaderGen::GenInterfaces(std::ofstream& stream) { for (auto& i : GetDocument().GetBlocks()) { if (i->GetType() != Block::TYPE_INTERFACE) @@ -49,127 +89,85 @@ void CProxyHeaderGen::GenInterfaces(std::ofstream& stream) { } void CProxyHeaderGen::GenInterface(std::ofstream& stream, - const Interface& inf) { - GenInterfaceDeclaration(stream, inf); - GenInterfaceDelegators(stream, inf); - GenInterfaceCtor(stream, inf); - GenInterfaceConnect(stream, inf); - GenInterfaceDtor(stream, inf); - GenInterfaceMethods(stream, inf); - GenInterfaceConnectSync(stream, inf); -} + const Interface& inf) { + for (auto& d: inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateBase(stream, inf, *d); + } + + GenInterfaceBase(stream, inf); -void CProxyHeaderGen::GenInterfaceDelegators(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) continue; - GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i); + + GenInterfaceMethodBase(stream, inf, *d); } } -void CProxyHeaderGen::GenInterfaceDelegator(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - const char handle[] = "typedef struct $$_s *rpc_port_$$_h;"; - - stream << NLine(1); - stream << GenTemplateString(handle, - [&]()->std::string { - return id + "_" + decl.GetID(); - }, - [&]()->std::string { - return id + "_" + decl.GetID(); - }); - - stream << NLine(1); - stream << GenTemplateString(CB_INTERFACE_DELEGATOR, - [&]()->std::string { - return GetReturnTypeString(decl.GetType()); - }, - [&]()->std::string { - return id + "_" + decl.GetID(); - }, - [&]()->std::string { - std::string str; - str += "void *user_data"; - for (auto& p : decl.GetParameters().GetParams()) { - str += ", "; - str += GetParamTypeString(p->GetParameterType().GetDirection(), - p->GetParameterType().GetBaseType()) + p->GetID(); - } - return str; - }); - - stream << ReplaceAll(CB_DELEGATE_CTOR, "##", id + "_" + decl.GetID()); - stream << ReplaceAll(CB_DELEGATE_DTOR, "##", id + "_" + decl.GetID()); - stream << GenTemplateString( - ReplaceAll(CB_DELEGATE_DISPOSER, "##", id + "_" + decl.GetID()), - [&]()->std::string { - return id; - }); -} +// @see #CB_INTERFACE_BASE +void CProxyHeaderGen::GenInterfaceBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); -void CProxyHeaderGen::GenInterfaceDeclaration(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_DECL, "##", - GetInterfaceIdWithNamespace(inf))); + stream << SmartIndent(code); } -void CProxyHeaderGen::GenInterfaceMethods(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) - continue; - stream << GenTemplateString( - ReplaceAll(CB_INTERFACE_METHODS, "##", - GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - return GetReturnTypeString(i->GetType()); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - std::string str; - for (auto& p : i->GetParameters().GetParams()) { - str += ", "; - if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) { - str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" + - p->GetParameterType().GetBaseType().ToString() + - "_h " + p->GetID(); - } else { - str += GetParamTypeString(p->GetParameterType().GetDirection(), - p->GetParameterType().GetBaseType()) + p->GetID(); - } - } - return str; - }); +std::string CProxyHeaderGen::GenDelegateParams(const Interface& inf, + const Declaration& decl) { + std::string params; + for (auto& p : decl.GetParameters().GetParams()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, inf) + + p->GetID(); } -} -void CProxyHeaderGen::GenInterfaceCtor(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CTOR, "##", - GetInterfaceIdWithNamespace(inf)); + return params; } -void CProxyHeaderGen::GenInterfaceConnect(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CONNECT, "##", - GetInterfaceIdWithNamespace(inf)); +// @see #CB_INTERFACE_DELEGATE_BASE +void CProxyHeaderGen::GenInterfaceDelegateBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + code = ReplaceAll(code, "", GenDelegateParams(inf, decl)); + + stream << SmartIndent(code); } -void CProxyHeaderGen::GenInterfaceDtor(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_DTOR, "##", - GetInterfaceIdWithNamespace(inf)); +std::string CProxyHeaderGen::GenMethodParams(const Interface& inf, + const Declaration& decl) { + std::string params; + for (auto& p : decl.GetParameters().GetParams()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, inf) + + p->GetID(); + } + + return params; } -void CProxyHeaderGen::GenInterfaceConnectSync(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CONNECT_SYNC, "##", - GetInterfaceIdWithNamespace(inf)); +// @see #CB_INTERFACE_METHOD_BASE +void CProxyHeaderGen::GenInterfaceMethodBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_BASE, "", + GetReturnTypeString(decl.GetType())); + code = ReplaceAll(code, "", GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + code = ReplaceAll(code, "", GenMethodParams(inf, decl)); + + stream << SmartIndent(code); } } // namespace tidl diff --git a/idlc/gen/c_proxy_header_gen.h b/idlc/gen/c_proxy_header_gen.h index 8dfa891f..6b578730 100644 --- a/idlc/gen/c_proxy_header_gen.h +++ b/idlc/gen/c_proxy_header_gen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,21 +33,22 @@ class CProxyHeaderGen : public CHeaderGeneratorBase { void OnFiniGen(std::ofstream& stream) override; private: - void GenInterfaces(std::ofstream& stream); + void GenInterfaceHandles(std::ofstream& stream); + void GenInterfaceHandle(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& inf, + const Declaration& decl); - private: + void GenInterfaces(std::ofstream& stream); void GenInterface(std::ofstream& stream, const Interface& inf); - void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf); - void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf); - void GenInterfaceMethods(std::ofstream& stream, const Interface& inf); - void GenInterfaceCtor(std::ofstream& stream, const Interface& inf); - void GenInterfaceConnect(std::ofstream& stream, const Interface& inf); - void GenInterfaceDtor(std::ofstream& stream, const Interface& inf); - void GenInterfaceConnectSync(std::ofstream& stream, const Interface& inf); - private: - void GenInterfaceDelegator(std::ofstream& stream, const std::string& id, - const Declaration& decl); + void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + void GenInterfaceBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceMethodBase(std::ofstream& stream, const Interface& info, + const Declaration& decl); + + std::string GenDelegateParams(const Interface& inf, const Declaration& decl); + std::string GenMethodParams(const Interface& inf, const Declaration& decl); }; } // namespace tidl diff --git a/idlc/gen/c_proxy_header_gen_cb.h b/idlc/gen/c_proxy_header_gen_cb.h index e6849e1a..0bb12311 100644 --- a/idlc/gen/c_proxy_header_gen_cb.h +++ b/idlc/gen/c_proxy_header_gen_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,62 +17,313 @@ #ifndef IDLC_C_GEN_C_PROXY_HEADER_GEN_CB_H_ #define IDLC_C_GEN_C_PROXY_HEADER_GEN_CB_H_ -const char CB_INTERFACE_DECL[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_HANDLE[] = R"__c_cb( -typedef struct ##_s *rpc_port_proxy_##_h; - -typedef struct { - void (*connected)(rpc_port_proxy_##_h h, void *user_data); - void (*disconnected)(rpc_port_proxy_##_h h, void *user_data); - void (*rejected)(rpc_port_proxy_##_h h, void *user_data); -} rpc_port_proxy_##_callback_s; +/** + * @brief The _ handle. + */ +typedef struct __s *__h; )__c_cb"; -const char CB_INTERFACE_CTOR[] = +constexpr const char CB_INTERFACE_DELEGATE_HANDLE[] = R"__c_cb( -int rpc_port_proxy_##_create(const char *stub_appid, - rpc_port_proxy_##_callback_s *callback, void *user_data, - rpc_port_proxy_##_h *h); +/** + * @brief The __ handle. + */ +typedef struct ___s *___h; )__c_cb"; -const char CB_INTERFACE_CONNECT[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate. + * The parameters of the callback function. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE[] = R"__c_cb( -int rpc_port_proxy_##_connect(rpc_port_proxy_##_h h); -)__c_cb"; +/** + * @brief Called when the event is received. + * + * @param[in] user_data The user data passed from the callback registration function + * @param[in] ... + * + * @see ___create() + */ +typedef void (*___cb)(void *user_data); -const char CB_INTERFACE_DTOR[] = -R"__c_cb( -int rpc_port_proxy_##_destroy(rpc_port_proxy_##_h h); -)__c_cb"; +/** + * @brief Creates a __ handle. + * + * @param[out] h The __ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memorya + * @see ___destroy() + * @see ___dispose() + * @see ___set_callback() + * @see ___set_once() + */ +int ___create(___h *h); -const char CB_INTERFACE_METHODS[] = -R"__c_cb( -$$rpc_port_proxy_##_invoke_$$(rpc_port_proxy_##_h h$$); -)__c_cb"; +/** + * @brief Destroys the __ handle. + * + * @param[in] h The __ 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 ___create() + */ +int ___destroy(___h h); -const char CB_INTERFACE_DELEGATOR[] = -R"__c_cb( -typedef $$(*$$)($$); -)__c_cb"; +/** + * @brief Creates and returns a copy of the given __ handle. + * + * @remarks A new created __ should be released using + * the ___destroy() if it's no longer needed. + * @param[in] h The __ handle + * @param[out] clone If successful, a new created __ 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 ___destroy() + */ +int ___clone(___h h, ___h *clone); -const char CB_DELEGATE_CTOR[] = -R"__c_cb( -rpc_port_##_h rpc_port_##_create(## callback, bool once, void *user_data); -)__c_cb"; +/** + * @brief Sets the callback function to the __ handle. + * + * @param[in] h The __ handle + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___set_callback(___h h, ___cb callback, void *user_data); -const char CB_DELEGATE_DISPOSER[] = -R"__c_cb( -int rpc_port_proxy_##_dispose(rpc_port_proxy_$$_h proxy, rpc_port_##_h delegate); +/** + * @brief Set the once flag to the __ handle. + * @details If the once flag is 'true', the delegate handle will be deleted after invocation. + * If the @a h handle is not used using the method, the handle should be released using + * the ___destroy() when it's no longer needed. + * If you don't want the delegate callback function to be called after it's used using the method, + * you should release the handle using the ___dispose(). + * + * @param[in] h The __ handle + * @param[in] once The flag if it's true, the delegate will be deleted after invocation + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___set_once(___h h, bool once); + +/** + * @brief Gets the ID of the __ handle. + * + * @param[in] h The __ handle + * @param[out] id The ID + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___get_id(___h h, int *id); + +/** + * @brief Gets the sequence ID of the __ handle. + * + * @param[in] h The __ handle + * @param[out] seq_id The Sequence ID + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___get_seq_id(___h h, int *seq_id); + +/** + * @brief Checks whether the delegate is for one-time or not. + * + * @param[in] h The __ handle + * @param[out] once The flag, it's true, the handle is for one-time + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___is_once(___h h, bool *once); + +/** + * @brief Gets the tag from the __ handle. + * + * @remarks The @a tag should be released using free(). + * @param[in] h The __ handle + * @param[out] tag The tag + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + */ +int ___get_tag(___h h, char **tag); + +/** + * @brief Disposes the __ handle from the _ handle. + * + * @param[in] proxy The _ handle + * @param[in] h The __ 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 ___create() + */ +int ___dispose(__h proxy, ___h h); )__c_cb"; -const char CB_DELEGATE_DTOR[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_BASE[] = R"__c_cb( -int rpc_port_##_destroy(rpc_port_##_h delegate); +/** + * @brief Called when the proxy is connected. + * @details The callback function is called when the proxy is connected to the stub. + * + * @param[in] h The _ handle + * @param[in] user_data The user data passed from the registeration function + * @see #__callback_s + */ +typedef void (*__connected_cb)(__h h, void *user_data); + +/** + * @brief Called when the proxy is disconnected. + * @details The callback function is called when the proxy is disconnected from the stub. + * + * @param[in] h The _ handle + * @param[in] user_data The user data passed from the registeration function + * @see #__callback_s + */ +typedef void (*__disconnected_cb)(__h h, void *user_data); + +/** + * @brief Called when the proxy is rejected. + * @details The callback function is called when the proxy is rejected to connect to the stub. + * + * @param[in] h The _ handle + * @param[in] user_data The user data passed from the registeration function + * @see #__callback_s + */ +typedef void (*__rejected_cb)(__h h, void *user_data); + +/** + * @brief The structure type containing the set of callback functions for handling proxy events. + * @details It is one of the input parameters of the __create() function. + * + * @see __connected_cb + * @see __disconnected_cb + * @see __rejected_cb + */ +typedef struct { + __connected_cb connected; /**< This callback function is called when the proxy is connected to the stub. */ + __disconnected_cb disconnected; /**< This callback function is called when the proxy is disconnected from the stub. */ + __rejected_cb rejected; /**< This callback function is called when the proxy is rejected to connect to the stub. */ +} __callback_s; + +/** + * @brief Creates a _ handle. + * @remarks The @a h handle should be released using + * the __destroy() if it's no longer needed. + * + * @param[in] stub_appid The application ID of the stub + * @param[in] callback The set of callback functions to handle proxy events + * @param[in] user_data The user data to be passed to the callback function + * @param[out] h The _ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see __destroy() + * @see #__callback_s + */ +int __create(const char *stub_appid, __callback_s *callback, void *user_data, __h *h); + +/** + * @brief Destroys the _ handle. + * + * @param[in] h The _ 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 __create() + */ +int __destroy(__h h); + +/** + * @brief Connects to the stub. + * + * @param[in] h The _ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_IO_ERROR I/O error + * @retval #RPC_PORT_ERROR_PERMISSION_DENIED Permission denied + */ +int __connect(__h h); + +/** + * @brief Connects to the stub synchronously. + * + * @param[in] h The _ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_IO_ERROR I/O error + * @retval #RPC_PORT_ERROR_PERMISSION_DENIED Permission denied + */ +int __connect_sync(__h h); )__c_cb"; -const char CB_INTERFACE_CONNECT_SYNC[] = +/** + * The type of the return value. + * The prefix of the interface. + * The of the interface. + * The name of the method. + * The parameters of the method. + */ +constexpr const char CB_INTERFACE_METHOD_BASE[] = R"__c_cb( -int rpc_port_proxy_##_connect_sync(rpc_port_proxy_##_h h); +/** + * @brief Calls the () method. + * @details The return value and args are decided by the interface declaration. + * You can get the result using get_last_result(). + * Before returning the function, the function sets the result using set_last_result(). + * @remarks The specific error code can be obtained using the get_last_result() function. Error codes are described in Exception section. + * @param[in] h The _ handle + * @param[in] ... + * @exception #RPC_PORT_ERROR_NONE Successful + * @exception #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @exception #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @exception #RPC_PORT_ERROR_IO_ERROR I/O error + */ +__invoke_(__h h); )__c_cb"; #endif // IDLC_C_GEN_C_PROXY_HEADER_GEN_CB_H_ diff --git a/idlc/gen/c_stub_body_gen.cc b/idlc/gen/c_stub_body_gen.cc index 68c4a0a4..12355e0c 100644 --- a/idlc/gen/c_stub_body_gen.cc +++ b/idlc/gen/c_stub_body_gen.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,17 @@ * limitations under the License. */ -#include "idlc/gen/c_stub_body_gen.h" +#include -namespace { +#include "idlc/gen/c_stub_body_gen.h" #include "idlc/gen/c_stub_body_gen_cb.h" -} namespace tidl { CStubBodyGen::CStubBodyGen(std::shared_ptr doc, std::shared_ptr options) - : CBodyGeneratorBase(doc), options_(options) {} + : CBodyGeneratorBase(doc), options_(options) { +} void CStubBodyGen::OnInitGen(std::ofstream& stream) { GenVersion(stream); @@ -33,601 +33,639 @@ void CStubBodyGen::OnInitGen(std::ofstream& stream) { GenIncludeHeader(stream); GenLogTag(stream, std::string("RPC_PORT_STUB")); GenLogDefinition(stream); - GenTypedefStubMethod(stream); + GenBaseDefinition(stream); + GenThreadEnableDefinition(stream); + GenInterfaceMethodHandlerType(stream); + GenInterfaceEnums(stream); + GenStructureDefs(stream); + GenInterfaceDefs(stream); + GenPrivateSharingListSet(stream); GenStructures(stream); GenInterfaces(stream); } -void CStubBodyGen::OnFiniGen(std::ofstream& stream) {} +void CStubBodyGen::OnFiniGen(std::ofstream& stream) { +} -void CStubBodyGen::GenInterfaces(std::ofstream& stream) { - for (auto& i : GetDocument().GetBlocks()) { - if (i->GetType() != Block::TYPE_INTERFACE) +// @see #CB_THREAD_ENABLE_DEF +void CStubBodyGen::GenThreadEnableDefinition(std::ofstream& stream) { + if (!options_->IsThreadEnabled()) + return; + + stream << std::string(CB_THREAD_ENABLE_DEF); +} + +// @see #CB_INTERFACE_METHOD_HANDLER_TYPE +void CStubBodyGen::GenInterfaceMethodHandlerType(std::ofstream& stream) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_HANDLER_TYPE, "", + GetHandlePrefix()); + + stream << SmartIndent(code); +} + +void CStubBodyGen::GenInterfaceEnums(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) continue; - const Interface &inf = static_cast(*i); - GenInterface(stream, inf); + auto& inf = static_cast(*b); + GenInterfaceEnum(stream, inf); } } -void CStubBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) { - GenInterfaceEnumerations(stream, inf); - GenInterfaceGlobalVariables(stream, inf); - GenInterfaceContext(stream, inf); - GenInterfaceDelegators(stream, inf); - GenInterfaceMethods(stream, inf); - GenInterfaceMethodTable(stream, inf); - GenInterfaceOnConnectedEventCB(stream, inf); - GenInterfaceOnDisconnectedEventCB(stream, inf); - GenInterfaceOnReceivedEventCB(stream, inf); - GenInterfaceAddPrivileges(stream, inf); - GenInterfaceRegister(stream, inf); - GenInterfaceUnregister(stream, inf); - GenInterfaceClientNumberGetter(stream, inf); -} - -void CStubBodyGen::GenInterfaceMethods(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) +void CStubBodyGen::GenInterfaceEnum(std::ofstream& stream, + const Interface& inf) { + GenInterfaceMethodEnumBase(stream, inf); + GenInterfaceDelegateEnumBase(stream, inf); +} + +// @see #CB_INTERFACE_METHOD_ENUM +std::string CStubBodyGen::GenMethodEnums(const Interface& inf) { + std::string method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, + "", GetHandlePrefix()); + method_enum = ReplaceAll(method_enum, "", inf.GetID()); + method_enum = ReplaceAll(method_enum, "", "RESULT_"); + std::string method_enums = RemoveLine(method_enum); + + method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, "", + GetHandlePrefix()); + method_enum = ReplaceAll(method_enum, "", inf.GetID()); + method_enum = ReplaceAll(method_enum, "", "CALLBACK_"); + method_enums += RemoveLine(method_enum); + + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) continue; - stream << SmartIndent(GenTemplateString(CB_INTERFACE_METHOD, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return GetMethodString(inf, *i); - })); + method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, "", + GetHandlePrefix()); + method_enum = ReplaceAll(method_enum, "", inf.GetID()); + method_enum = ReplaceAll(method_enum, "", + d->GetID()); + + method_enums += RemoveLine(method_enum); } + std::transform(method_enums.begin(), method_enums.end(), method_enums.begin(), + ::toupper); + + return method_enums; } -void CStubBodyGen::GenInterfaceMethodTable(std::ofstream& stream, - const Interface& inf) { - std::string str; - int cnt = 0; +// @see #CB_INTERFACE_METHOD_ENUM_BASE +void CStubBodyGen::GenInterfaceMethodEnumBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", GenMethodEnums(inf)); + + stream << SmartIndent(code); +} - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) +// @see #CB_INTERFACE_DELEGATE_ENUM +std::string CStubBodyGen::GenDelegateEnums(const Interface& inf) { + unsigned int num = 1; + std::string method_enums; + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) continue; - str += GenTemplateString(CB_INTERFACE_METHOD_FORMAT, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf) + "_METHOD_" + i->GetID(); - }, - [&]()->std::string { - return "__" + GetInterfaceIdWithNamespace(inf) + "_method_" - + i->GetID(); - }); - cnt++; + + std::string method_enum = ReplaceAll(CB_INTERFACE_DELEGATE_ENUM, + "", GetHandlePrefix()); + method_enum = ReplaceAll(method_enum, "", inf.GetID()); + method_enum = ReplaceAll(method_enum, "", + d->GetID()); + method_enum = ReplaceAll(method_enum, "", std::to_string(num++)); + + method_enums += RemoveLine(method_enum); } + std::transform(method_enums.begin(), method_enums.end(), method_enums.begin(), + ::toupper); - if (cnt == 0) - return; + return method_enums; +} + +// @see #CB_INTERFACE_DELEGATE_ENUM_BASE +void CStubBodyGen::GenInterfaceDelegateEnumBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_ENUM_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", GenDelegateEnums(inf)); + + stream << SmartIndent(code); +} + +void CStubBodyGen::GenInterfaceDefs(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; - stream << NLine(1); - stream << SmartIndent(GenTemplateString(CB_INTERFACE_METHOD_TABLE, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - return str; - })); -} - -void CStubBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream, - const Interface& inf) { - if (options_->IsThreadEnabled()) { - stream << SmartIndent( - ReplaceAll(CB_INTERFACE_THREAD_METHODS, "##", - GetInterfaceIdWithNamespace(inf))); + auto& inf = static_cast(*b); + GenInterfaceDef(stream, inf); } +} - stream << SmartIndent( - ReplaceAll(CB_INTERFACE_ON_CONNECTED, "##", - GetInterfaceIdWithNamespace(inf))); +void CStubBodyGen::GenInterfaceDef(std::ofstream& stream, + const Interface& inf) { + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateDef(stream, inf, *d); + } + + GenInterfaceContextDef(stream, inf); + GenInterfaceBaseDef(stream, inf); } -void CStubBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent( - ReplaceAll(CB_INTERFACE_ON_DISCONNECTED, "##", - GetInterfaceIdWithNamespace(inf))); +// @see #CB_INTERFACE_DELEGATE_DEF +void CStubBodyGen::GenInterfaceDelegateDef(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + + stream << SmartIndent(code); } -void CStubBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream, - const Interface& inf) { - if (options_->IsThreadEnabled()) { - stream << SmartIndent( - ReplaceAll(CB_INTERFACE_THREAD_ON_RECEIVED, "##", - GetInterfaceIdWithNamespace(inf))); - } else { - stream << SmartIndent( - ReplaceAll(CB_INTERFACE_ON_RECEIVED, "##", - GetInterfaceIdWithNamespace(inf))); +// @see #CB_INTERFACE_CONTEXT_DEF +void CStubBodyGen::GenInterfaceContextDef(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_BASE_DEF +void CStubBodyGen::GenInterfaceBaseDef(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_BASE_DEF, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + + stream << SmartIndent(code); +} + +void CStubBodyGen::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + + const Interface &inf = static_cast(*i); + GenInterface(stream, inf); } } -void CStubBodyGen::GenInterfaceRegister(std::ofstream& stream, - const Interface& inf) { - std::string r_str = ReplaceAll(CB_INTERFACE_REGISTER, "##", - GetInterfaceIdWithNamespace(inf)); - - stream << SmartIndent(GenTemplateString(r_str, - [&]()->std::string { - if (options_->IsThreadEnabled()) - return CB_INTERFACE_THREAD_CREATE; - return ""; - })); -} - -void CStubBodyGen::GenInterfaceUnregister(std::ofstream& stream, - const Interface& inf) { - std::string r_str = ReplaceAll(CB_INTERFACE_UNREGISTER, "##", - GetInterfaceIdWithNamespace(inf)); - - stream << SmartIndent(GenTemplateString(r_str, - [&]()->std::string { - if (options_->IsThreadEnabled()) - return "job_h job;"; - return ""; - }, - [&]()->std::string { - if (options_->IsThreadEnabled()) - return CB_INTERFACE_THREAD_DESTROY; - return ""; - })); -} - -void CStubBodyGen::GenInterfaceGlobalVariables(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_GLOBALS, "##", - GetInterfaceIdWithNamespace(inf))); -} - -std::string CStubBodyGen::GetMethodString(const Interface& inf, - const Declaration& decl) { - std::string str; - const char port_setter[] = "rpc_port_$$_set_port($$, callback_port);\n"; - const char setter[] = "$$($$, $$);\n"; - const char do_while_block[] = - "do {\n" \ - " rpc_port_parcel_h result;\n" \ - "\n" \ - " rpc_port_parcel_create(&result);\n" \ - " rpc_port_parcel_write_int32(result, $$_METHOD_Result);\n" \ - "$$" \ - " r = rpc_port_parcel_send(result, port);\n" \ - " rpc_port_parcel_destroy(result);\n" \ - "} while (0);\n"; - const char ternary_operation[] = "## ? ## : \"\""; - int cnt = 0; - for (auto& i : decl.GetParameters().GetParams()) { - if (IsDelegateType(inf, i->GetParameterType().GetBaseType())) { - str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" + - i->GetParameterType().GetBaseType().ToString() + "_h " + - i->GetID() + " = NULL;" + NLine(1); - } else if (i->GetParameterType().GetBaseType().IsUserDefinedType() || - i->GetParameterType().GetBaseType().ToString() == "list" || - i->GetParameterType().GetBaseType().ToString() == "array") { - str += GetReturnTypeString(i->GetParameterType().GetBaseType()) + - i->GetID() + " = NULL;" + NLine(1); - } else { - str += GetReturnTypeString(i->GetParameterType().GetBaseType()) + - i->GetID() + ";" + NLine(1); - } - if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN) - cnt++; +void CStubBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) { + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateBase(stream, inf, *d); } - str += NLine(1); - for (auto& i : decl.GetParameters().GetParams()) { - if (i->GetParameterType().GetDirection() != ParameterType::Direction::IN) + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) continue; - if (i->GetParameterType().GetBaseType().IsUserDefinedType() || - i->GetParameterType().GetBaseType().ToString() == "list" || - i->GetParameterType().GetBaseType().ToString() == "array") { - if (IsDelegateType(inf, i->GetParameterType().GetBaseType())) { - str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" + - i->GetParameterType().GetBaseType().ToString() + - "_create(&" + i->GetID() + ");" + NLine(1); - str += "\nif (!" + i->GetID() + ") {\n"; - str += " _E(\"Failed to create handle\");\n"; - str += " return -1;\n"; - str += "}\n\n"; - str += GenTemplateString(port_setter, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf) + "_" + - i->GetParameterType().GetBaseType().ToString(); - }, - [&]()->std::string { - return i->GetID(); - }); - } else { - str += GetConstructorString(i->GetParameterType().GetBaseType(), - i->GetID()); - } - } + GenInterfaceMethodHandlerBase(stream, inf, *d); + } + + GenInterfaceMethodTable(stream, inf); + GenInterfaceContextBase(stream, inf); + GenInterfaceBase(stream, inf); +} + +// @see #CB_INTERFACE_CONTEXT_BASE +void CStubBodyGen::GenInterfaceContextBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); - str += GenTemplateString(setter, - [&]()->std::string { - return GetParcelReadFunctionString( - i->GetParameterType().GetBaseType(), true); - }, - [&]()->std::string { - return "parcel"; - }, - [&]()->std::string { - if (i->GetParameterType().GetBaseType().IsUserDefinedType() || - i->GetParameterType().GetBaseType().ToString() == "list" || - i->GetParameterType().GetBaseType().ToString() == "array") - return "&" + i->GetID() + "->parcelable, " + i->GetID(); - return "&" + i->GetID(); - }); + stream << SmartIndent(code); +} + +std::string CStubBodyGen::GenDelegateParams(const Interface& inf, + const Declaration& decl) { + std::string params; + for (auto& p : decl.GetParameters().GetParams()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, inf) + + p->GetID(); } - if (cnt > 0) - str += NLine(1); + return params; +} + +std::string CStubBodyGen::GenDelegateParamsCheck(const Interface& inf, + const Declaration& decl) { + std::string params_check; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array" || + type.ToString() == "bundle" || + type.ToString() == "string" || + type.ToString() == "file") + params_check += " || " + p->GetID() + " == nullptr"; + } - if (decl.GetMethodType() == Declaration::MethodType::SYNC && - decl.GetType().ToString() != "void") { - str += GetReturnTypeString(decl.GetType()) + "ret = "; + return params_check; +} + +// @see #CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_WRITE +// @see #CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_WRITE +// @see #CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE +// @see #CB_INTERFACE_DELEGATE_BASE_PARCEL_WRITE +std::string CStubBodyGen::GenDelegateParcelWrite(const Interface& inf, + const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + std::string parcel_write_code; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll( + CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_WRITE, "", + p->GetID()); + parcel_write_code += GetPrivateSharingString(type, inf, "h->port", + p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "string") { + parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE, + "", p->GetID()); + parcel_write_code += GetPrivateSharingString(type, inf, "h->port", + p->GetID()); + } else { + parcel_write_code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE_PARCEL_WRITE, + "", GetParcelType(type)); + parcel_write_code = ReplaceAll(parcel_write_code, "", p->GetID()); + } + + code += parcel_write_code; } - str += "context->callback." + decl.GetID() + "(context"; - for (auto& i : decl.GetParameters().GetParams()) { - str += ", "; - if (i->GetParameterType().GetDirection() != ParameterType::Direction::IN) - str += "&" + i->GetID(); - else - str += i->GetID(); + return RemoveLine(code); +} + +// @see #CB_INTERFACE_DELEGATE_BASE +void CStubBodyGen::GenInterfaceDelegateBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + code = ReplaceAll(code, "", GenDelegateParams(inf, decl)); + code = ReplaceAll(code, "", + GenDelegateParamsCheck(inf, decl)); + + std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() + + "_DELEGATE_" + decl.GetID(); + std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(), + ::toupper); + code = ReplaceAll(code, "", enum_value); + code = ReplaceAll(code, "", + GenDelegateParcelWrite(inf, decl)); + + stream << SmartIndent(code); +} + +std::string CStubBodyGen::GenMethodHandlerArgsDecl(const Interface& inf, + const Declaration& decl) { + std::string args_decl; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + args_decl += GetArgTypeString(type, inf) + p->GetID() + " = " + + GetErrorValue(type) + ";" + NLine(1); } - str += ", context->user_data);" + NLine(1); + if (decl.GetMethodType() == Declaration::MethodType::SYNC) { - str += GenTemplateString(do_while_block, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - std::string s; - for (auto& i : decl.GetParameters().GetParams()) { - if (i->GetParameterType().GetDirection() == - ParameterType::Direction::IN) - continue; - s += GenTemplateString(setter, - [&]()->std::string { - return GetParcelWriteFunctionString( - i->GetParameterType().GetBaseType(), true); - }, - [&]()->std::string { - return "result"; - }, - [&]()->std::string { - auto& t = i->GetParameterType().GetBaseType(); - if (t.IsUserDefinedType() || t.ToString() == "list" || - t.ToString() == "array") - return "&" + i->GetID() + "->parcelable, " + i->GetID(); - else if (t.ToString() == "string" || t.ToString() == "file") - return ReplaceAll(ternary_operation, "##", i->GetID()); - return i->GetID(); - }); - } - if (decl.GetType().ToString() != "void") { - s += GenTemplateString(setter, - [&]()->std::string { - return GetParcelWriteFunctionString(decl.GetType(), true); - }, - [&]()->std::string { - return "result"; - }, - [&]()->std::string { - if (decl.GetType().IsUserDefinedType() || - decl.GetType().ToString() == "list" || - decl.GetType().ToString() == "array") - return "&ret->parcelable, ret"; - else if (decl.GetType().ToString() == "string" || - decl.GetType().ToString() == "file") - return ReplaceAll(ternary_operation, "##", "ret"); - return "ret"; - }); - } - return s; - }); - } + args_decl += "rpc_port_parcel_h parcel_;" + NLine(1); + args_decl += GetArgTypeString(decl.GetType(), inf) + "res_ = " + + GetErrorValue(decl.GetType()) + ";" + NLine(1); + } - for (auto& i : decl.GetParameters().GetParams()) { - str += NLine(1); - if (IsDelegateType(inf, i->GetParameterType().GetBaseType())) { - str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" + - i->GetParameterType().GetBaseType().ToString() + - "_destroy(" + i->GetID() + ");"; + return args_decl; +} + +// @see #CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ +// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_READ +std::string CStubBodyGen::GenMethodHandlerParcelRead(const Interface& inf, + const Declaration& decl) { + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + std::string parcel_read_code; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type)) { + parcel_read_code = ReplaceAll( + CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ, "", + GetHandlePrefix()); + parcel_read_code = ReplaceAll(parcel_read_code, "", + GetFullNameFromType(type, inf)); + parcel_read_code = ReplaceAll(parcel_read_code, "", p->GetID()); + } else if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_read_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + parcel_read_code = ReplaceAll(parcel_read_code, "", + GetFullNameFromType(type, inf)); + parcel_read_code = ReplaceAll(parcel_read_code, "", p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ, + "", p->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ, + "", p->GetID()); } else { - str += GetDestructorString(i->GetParameterType().GetBaseType(), - i->GetID()); + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ, + "", GetParcelType(type)); + parcel_read_code = ReplaceAll(parcel_read_code, "", p->GetID()); } - } - str += GetDestructorString(decl.GetType(), "ret"); + code += parcel_read_code; + } - return str; + return RemoveLine(code); } -std::string CStubBodyGen::GetAddPrivilegeString(const std::string& id, - const Attribute& attr) { - std::string str; +// @see #CB_INTERFACE_METHOD_CALLBACK_INVOKE +std::string CStubBodyGen::GenMethodHandlerCallbackInvoke( + const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_INVOKE, + "", decl.GetID()); - str += GenTemplateString(CB_INTERFACE_PRIVILEGE_BLOCK, - [&]()->std::string { - return "rpc_port_stub_add_privilege(__" + id + - "_stub, \"" + attr.GetValue() + "\")"; - }, - [&]()->std::string { - return attr.GetValue(); - }); - return str; -} + if (decl.GetMethodType() == Declaration::MethodType::SYNC) + code = ReplaceAll(code, "", "res_ = "); + else + code = ReplaceAll(code, "", ""); -std::string CStubBodyGen::GetTrustedModeString(const std::string& id, - const Attribute& attr) { - std::string str; + std::string args; + for (auto& p : decl.GetParameters().GetParams()) { + args += ", "; + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) + args += "&"; - str += GenTemplateString(CB_INTERFACE_TRUSTED_MODE_BLOCK, - [&]()->std::string { - return "rpc_port_stub_set_trusted(__" + id + - "_stub, " + attr.GetValue() + ")"; - }, - [&]()->std::string { - return attr.GetValue(); - }); - return str; -} + args += p->GetID(); + } + code = ReplaceAll(code, "", args); + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_PARCEL_WRITE_PRE +// @see #CB_INTERFACE_METHOD_PARCEL_WRITE_POST +// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_WRITE +std::string CStubBodyGen::GenMethodHandlerParcelWrite(const Interface& inf, + const Declaration& decl) { + std::string code; + if (decl.GetMethodType() != Declaration::MethodType::SYNC) + return code; + + std::string name = inf.GetID(); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + code = ReplaceAll(CB_INTERFACE_METHOD_PARCEL_WRITE_PRE, "", + name); + + std::string parcel_write_code; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() == ParameterType::Direction::IN) + continue; + + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "", + p->GetID()); + parcel_write_code += GetPrivateSharingString(type, inf, "port", + p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "string") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", p->GetID()); + parcel_write_code += GetPrivateSharingString(type, inf, "port", + p->GetID()); + } else { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE, + "", GetParcelType(type)); + parcel_write_code = ReplaceAll(parcel_write_code, "", p->GetID()); + } + + code += parcel_write_code; + } -void CStubBodyGen::GenInterfaceDelegators(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + auto& type = decl.GetType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "", "res_"); + parcel_write_code += GetPrivateSharingString(type, inf, "port", "res_"); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE, + "", "res_"); + } else if (type.ToString() == "string") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", "res_"); + } else if (type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", "res_"); + parcel_write_code += GetPrivateSharingString(type, inf, "port", "res_"); + } else { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE, + "", GetParcelType(type)); + parcel_write_code = ReplaceAll(parcel_write_code, "", "res_"); + } + + code += parcel_write_code; + code += std::string(CB_INTERFACE_METHOD_PARCEL_WRITE_POST); + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_USER_DEFINED_FREE +// @see #CB_INTERFACE_METHOD_BUNDLE_FREE +// @see #CB_INTERFACE_METHOD_STRING_FREE +std::string CStubBodyGen::GenMethodHandlerArgsFree(const Interface& inf, + const Declaration& decl) { + std::string free_code; + std::string code; + for (auto& p : decl.GetParameters().GetParams()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_FREE, + "", GetHandlePrefix()); + free_code = ReplaceAll(free_code, "", + GetFullNameFromType(type, inf)); + free_code = ReplaceAll(free_code, "", p->GetID()); + } else if (type.ToString() == "bundle") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_FREE, + "", p->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_FREE, + "", p->GetID()); + } else { + free_code.clear(); + } + + code += free_code; + } + + if (decl.GetMethodType() == Declaration::MethodType::SYNC) { + auto& type = decl.GetType(); + if (IsDelegateType(inf, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_FREE, + "", GetHandlePrefix()); + free_code = ReplaceAll(free_code, "", + GetFullNameFromType(type, inf)); + free_code = ReplaceAll(free_code, "", "res_"); + } else if (type.ToString() == "bundle") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_FREE, + "", "res_"); + } else if (type.ToString() == "string" || type.ToString() == "file") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_FREE, + "", "res_"); + } else { + free_code.clear(); + } + + code += free_code; + } + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_HANDLER_BASE +void CStubBodyGen::GenInterfaceMethodHandlerBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_HANDLER_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + code = ReplaceAll(code, "", + GenMethodHandlerArgsDecl(inf, decl)); + code = ReplaceAll(code, "", + GenMethodHandlerParcelRead(inf, decl)); + code = ReplaceAll(code, "", + GenMethodHandlerCallbackInvoke(decl)); + code = ReplaceAll(code, "", + GenMethodHandlerParcelWrite(inf, decl)); + code = ReplaceAll(code, "", + GenMethodHandlerArgsFree(inf, decl)); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_METHOD_HANDLER +std::string CStubBodyGen::GenMethodHandlers(const Interface& inf) { + std::string code; + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) continue; - GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i); + + std::string enum_value = GetHandlePrefix() + "_" + inf.GetID() + + "_METHOD_" + d->GetID(); + std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(), + ::toupper); + std::string method_handler = ReplaceAll(CB_INTERFACE_METHOD_HANDLER, + "", enum_value); + method_handler = ReplaceAll(method_handler, "", GetHandlePrefix()); + method_handler = ReplaceAll(method_handler, "", inf.GetID()); + method_handler = ReplaceAll(method_handler, "", d->GetID()); + + code += RemoveLine(method_handler); } + + return code; } -void CStubBodyGen::GenInterfaceDelegator(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - GenInterfaceDelegatorDeclaration(stream, id, decl); - GenInterfaceDelegatorSerializer(stream, id, decl); - GenInterfaceDelegatorDeserializer(stream, id, decl); - GenInterfaceDelegatorConstructor(stream, id, decl); - GenInterfaceDelegatorDestructor(stream, id, decl); - GenInterfaceDelegatorCloner(stream, id, decl); - GenInterfaceDelegatorInvoker(stream, id, decl); - GenInterfaceDelegatorPortSetter(stream, id, decl); -} - -void CStubBodyGen::GenInterfaceDelegatorDeclaration(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent(GenTemplateString(CB_INTERFACE_DELEGATOR_DECL, - [&]()->std::string { - return id + "_" + decl.GetID(); - })); -} - -void CStubBodyGen::GenInterfaceDelegatorConstructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_INTERFACE_DELEGATOR_CTOR, "##", id + "_" + decl.GetID()), - [&]()->std::string { - return id; - }, - [&]()->std::string { - return decl.GetID(); - })); -} - -void CStubBodyGen::GenInterfaceDelegatorDestructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent( - ReplaceAll(CB_INTERFACE_DELEGATOR_DTOR, "##", id + "_" + decl.GetID())); -} - -void CStubBodyGen::GenInterfaceDelegatorSerializer(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_DELEGATOR_SERIALIZER, "##", id + "_" + decl.GetID())); -} - -void CStubBodyGen::GenInterfaceDelegatorDeserializer(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_DELEGATOR_DESERIALIZER, "##", id + "_" + decl.GetID())); -} - -void CStubBodyGen::GenInterfaceDelegatorCloner(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_DELEGATOR_CLONER, "##", id + "_" + decl.GetID())); -} - -void CStubBodyGen::GenInterfaceDelegatorInvoker(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - const char parcel[] = "$$(parcel, $$);\n"; - const char ternary_operation[] = "## ? ## : \"\""; - stream << SmartIndent(GenTemplateString(CB_INTERFACE_DELEGATOR_INVOKER, - [&]()->std::string { - return id + "_" + decl.GetID(); - }, - [&]()->std::string { - std::string str; - str += "rpc_port_" + id + "_" + decl.GetID() + "_h h"; - for (auto& i : decl.GetParameters().GetParams()) { - str += ", "; - str += GetParamTypeString(i->GetParameterType().GetDirection(), - i->GetParameterType().GetBaseType()) + i->GetID(); - } - return str; - }, - [&]()->std::string { - return id; - }, - [&]()->std::string { - std::string str; - for (auto& i : decl.GetParameters().GetParams()) { - str += GenTemplateString(parcel, - [&]()->std::string { - return GetParcelWriteFunctionString( - i->GetParameterType().GetBaseType(), true); - }, - [&]()->std::string { - auto& t = i->GetParameterType().GetBaseType(); - if (t.IsUserDefinedType() || t.ToString() == "list" || - t.ToString() == "array") - return "&" + i->GetID() + "->parcelable, " + i->GetID(); - else if (t.ToString() == "string" || t.ToString() == "file") - return ReplaceAll(ternary_operation, "##", i->GetID()); - return i->GetID(); - }); - } - return str; - })); -} - -void CStubBodyGen::GenInterfaceDelegatorPortSetter(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_DELEGATOR_PORT_SETTER, "##", id + "_" + decl.GetID())); -} - -void CStubBodyGen::GenInterfaceContext(std::ofstream& stream, - const Interface& inf) { - GenInterfaceContextDeclaration(stream, inf); - GenInterfaceContextConstructor(stream, inf); - GenInterfaceContextDestructor(stream, inf); - GenInterfaceContextFinder(stream, inf); - GenInterfaceContextTagSetter(stream, inf); - GenInterfaceContextTagGetter(stream, inf); - GenInterfaceContextSenderGetter(stream, inf); -} - -void CStubBodyGen::GenInterfaceContextDeclaration(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_INTERFACE_CONTEXT_DECL, "##", - GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - if (options_->IsThreadEnabled()) - return std::string(CB_INTERFACE_CONTEXT_DECL_THREAD_ELEM); - return ""; - })); - - if (options_->IsThreadEnabled()) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_THREAD_FEATURE, "##", GetInterfaceIdWithNamespace(inf))); +// @see #CB_INTERFACE_METHOD_TABLE +void CStubBodyGen::GenInterfaceMethodTable(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_TABLE, "", + inf.GetID()); + code = ReplaceAll(code, "", GenMethodHandlers(inf)); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_PRIVILEGE_ADD +// @see #CB_INTERFACE_TRUSTED_SET +std::string CStubBodyGen::GenAccessControlSet(const Interface& inf) { + std::string code; + for (auto& attr : inf.GetAttributes().GetAttrs()) { + if (attr->GetKey() == "privilege") { + std::string privilege_add = ReplaceAll(CB_INTERFACE_PRIVILEGE_ADD, + "", inf.GetID()); + privilege_add = ReplaceAll(privilege_add, "", + attr->GetValue()); + + code += privilege_add; + } else if (attr->GetKey() == "trusted" && attr->GetValue() == "true") { + std::string trusted_set = ReplaceAll(CB_INTERFACE_TRUSTED_SET, + "", inf.GetID()); + + code += trusted_set; + } } + + return RemoveLine(code); } -void CStubBodyGen::GenInterfaceContextConstructor(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_INTERFACE_CONTEXT_CTOR, "##", - GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - if (options_->IsThreadEnabled()) - return std::string(CB_INTERFACE_CONTEXT_CTOR_THREAD_IMPL); - return ""; - })); -} - -void CStubBodyGen::GenInterfaceContextDestructor(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(GenTemplateString( - ReplaceAll(CB_INTERFACE_CONTEXT_DTOR, "##", - GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - if (options_->IsThreadEnabled()) - return std::string(CB_INTERFACE_CONTEXT_DTOR_THREAD_VARS); - return ""; - }, - [&]()->std::string { - if (options_->IsThreadEnabled()) - return std::string(CB_INTERFACE_CONTEXT_DTOR_THREAD_IMPL); - return ""; - })); -} - -void CStubBodyGen::GenInterfaceContextFinder(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_CONTEXT_FINDER, "##", GetInterfaceIdWithNamespace(inf))); -} - -void CStubBodyGen::GenInterfaceContextTagSetter(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_CONTEXT_TAG_SETTER, "##", GetInterfaceIdWithNamespace(inf))); -} - -void CStubBodyGen::GenInterfaceContextTagGetter(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_CONTEXT_TAG_GETTER, "##", GetInterfaceIdWithNamespace(inf))); -} - -void CStubBodyGen::GenInterfaceContextSenderGetter(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll( - CB_INTERFACE_CONTEXT_GET_SENDER, "##", GetInterfaceIdWithNamespace(inf))); -} - -void CStubBodyGen::GenTypedefStubMethod(std::ofstream& stream) { - stream << CB_STUB_METHOD_TYPE; -} - -void CStubBodyGen::GenInterfaceAddPrivileges(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(GenTemplateString(CB_INTERFACE_ADD_PRIVILEGE, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - std::string str; - for (auto& a : inf.GetAttributes().GetAttrs()) { - if (a->GetKey() == "privilege") { - str += GetAddPrivilegeString( - GetInterfaceIdWithNamespace(inf), *a); - str += NLine(1); - } else if (a->GetKey() == "trusted" && a->GetValue() == "true") { - str += GetTrustedModeString(GetInterfaceIdWithNamespace(inf), *a); - str += NLine(1); - } - } - - if (!str.empty()) - str = SmartIndent("int r;\n\n") + str; - return str; - })); -} - -void CStubBodyGen::GenInterfaceClientNumberGetter(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(ReplaceAll(CB_INTERFACE_CLIENT_NUMBER_GETTER, "##", - GetInterfaceIdWithNamespace(inf))); +// @see #CB_INTERFACE_BASE +void CStubBodyGen::GenInterfaceBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", GenAccessControlSet(inf)); + + stream << SmartIndent(code); } } // namespace tidl diff --git a/idlc/gen/c_stub_body_gen.h b/idlc/gen/c_stub_body_gen.h index f7877742..31b55db8 100644 --- a/idlc/gen/c_stub_body_gen.h +++ b/idlc/gen/c_stub_body_gen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,77 +35,51 @@ class CStubBodyGen : public CBodyGeneratorBase { void OnFiniGen(std::ofstream& stream) override; private: + void GenThreadEnableDefinition(std::ofstream& stream); + void GenInterfaceMethodHandlerType(std::ofstream& stream); + void GenInterfaceEnums(std::ofstream& stream); + void GenInterfaceEnum(std::ofstream& stream, const Interface& inf); + void GenInterfaceMethodEnumBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateEnumBase(std::ofstream& stream, + const Interface& inf); + + void GenInterfaceDefs(std::ofstream& stream); + void GenInterfaceDef(std::ofstream& stream, const Interface& inf); + void GenInterfaceContextDef(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateDef(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + void GenInterfaceBaseDef(std::ofstream& stream, const Interface& inf); + void GenInterfaces(std::ofstream& stream); void GenInterface(std::ofstream& stream, const Interface& inf); - void GenTypedefStubMethod(std::ofstream& stream); - void GenInterfaceMethods(std::ofstream& stream, const Interface& inf); + void GenInterfaceContextBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + void GenInterfaceMethodHandlerBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl); void GenInterfaceMethodTable(std::ofstream& stream, const Interface& inf); - void GenInterfaceOnConnectedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceOnDisconnectedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceOnReceivedEventCB(std::ofstream& stream, - const Interface& inf); - void GenInterfaceRegister(std::ofstream& stream, const Interface& inf); - void GenInterfaceUnregister(std::ofstream& stream, const Interface& inf); - void GenInterfaceGlobalVariables(std::ofstream& stream, const Interface& inf); - void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf); - void GenInterfaceContext(std::ofstream& stream, const Interface& inf); - void GenInterfaceAddPrivileges(std::ofstream& stream, const Interface& inf); - void GenInterfaceClientNumberGetter(std::ofstream& stream, - const Interface& inf); + void GenInterfaceBase(std::ofstream& stream, const Interface& inf); - private: - void GenInterfaceContextDeclaration(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextConstructor(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextDestructor(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextFinder(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextTagSetter(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextTagGetter(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextSenderGetter(std::ofstream& stream, - const Interface& inf); + std::string GenMethodEnums(const Interface& inf); + std::string GenDelegateEnums(const Interface& inf); - private: - void GenInterfaceDelegator(std::ofstream& stream, const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDeclaration(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorConstructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDestructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorSerializer(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDeserializer(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorCloner(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorInvoker(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorPortSetter(std::ofstream& stream, - const std::string& id, - const Declaration& decl); + std::string GenDelegateParams(const Interface& inf, const Declaration& decl); + std::string GenDelegateParamsCheck(const Interface& inf, + const Declaration& decl); + std::string GenDelegateParcelWrite(const Interface& inf, + const Declaration& decl); - private: - std::string GetMethodString(const Interface& id, const Declaration& decl); - std::string GetAddEventCBString(const std::string& id); - std::string GetAddPrivilegeString(const std::string& id, - const Attribute& attr); - std::string GetTrustedModeString(const std::string& id, - const Attribute& attr); + std::string GenMethodHandlerArgsDecl(const Interface& inf, + const Declaration& decl); + std::string GenMethodHandlerParcelRead(const Interface& inf, + const Declaration& decl); + std::string GenMethodHandlerCallbackInvoke(const Declaration& decl); + std::string GenMethodHandlerParcelWrite(const Interface& inf, + const Declaration& decl); + std::string GenMethodHandlerArgsFree(const Interface& inf, + const Declaration& decl); + std::string GenMethodHandlers(const Interface& inf); + std::string GenAccessControlSet(const Interface& inf); private: std::shared_ptr options_; diff --git a/idlc/gen/c_stub_body_gen_cb.h b/idlc/gen/c_stub_body_gen_cb.h index a7ef172f..d0739590 100644 --- a/idlc/gen/c_stub_body_gen_cb.h +++ b/idlc/gen/c_stub_body_gen_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,741 +17,1146 @@ #ifndef IDLC_C_GEN_C_STUB_BODY_GEN_CB_H_ #define IDLC_C_GEN_C_STUB_BODY_GEN_CB_H_ -const char CB_INTERFACE_METHOD[] = +constexpr const char CB_THREAD_ENABLE_DEF[] = R"__c_cb( -static int __$$_method_$$(rpc_port_h port, rpc_port_parcel_h parcel, void *data) -{ - rpc_port_stub_$$_context_h context = data; - rpc_port_h callback_port; - int r; +#define TIDL_THREAD_ENABLE 1 +)__c_cb"; - r = rpc_port_stub_get_port(__$$_stub, RPC_PORT_PORT_CALLBACK, context->instance, &callback_port); - if (r != 0) { - _E("Failed to get callback port"); - return -1; - } +/** + * The prefix of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_HANDLER_TYPE[] = +R"__c_cb( +typedef int (*_method_handler)(rpc_port_h port, rpc_port_parcel_h parcel, void *data); +)__c_cb"; -$$ - return r; -} +/** + * The enumeration declarations of methods. + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_ENUM_BASE[] = +R"__c_cb( +typedef enum { + +} __method_e; )__c_cb"; -const char CB_INTERFACE_METHOD_TABLE[] = -R"__c_cb(static stub_method __$$_method_table[] = {$$ -}; +/** + * The uppercase prefix of the interface. + * The uppercase name of the interface. + * The uppercase method name of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_ENUM[] = +R"__c_cb( +__METHOD_, )__c_cb"; -const char CB_INTERFACE_METHOD_FORMAT[] = +/** + * The enumeration declarations of deleagtes. + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_ENUM_BASE[] = R"__c_cb( -[$$] = $$,)__c_cb"; +typedef enum { + +} __delegate_e; +)__c_cb"; -const char CB_INTERFACE_THREAD_METHODS[] = +/** + * The uppercase prefix of the interface. + * The uppercase name of the interface. + * The uppercase delegate name of the interface. + * The number of the delegate. + */ +constexpr const char CB_INTERFACE_DELEGATE_ENUM[] = R"__c_cb( -static int __run_pending_job(void) -{ - int cmd = -1; - job_h job; - int r = 0; +__DELEGATE_ = , +)__c_cb"; - if (g_queue_is_empty(__job_queue)) { - _E("Empty queue"); - return -1; - } +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_BASE_DEF[] = +R"__c_cb( +typedef struct __s { + rpc_port_stub_h stub; + __callback_s callback; + void *user_data; + GList* contexts; + GList* callback_ports; + GRecMutex mutex; +} __t; + +static __t __; +)__c_cb"; - job = g_queue_pop_head(__job_queue); - rpc_port_parcel_read_int32(job->parcel, &cmd); - if (cmd > 1 && cmd < (sizeof(__##_method_table) / sizeof(__##_method_table[0]))) { - if (__##_method_table[cmd]) - r = __##_method_table[cmd](job->port, job->parcel, job->context); - } else { - _E("Unknown Command(%d)", cmd); - r = -1; - } +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_DEF[] = +R"__c_cb( +typedef struct __context_s { + char *sender; + char *instance; + rpc_port_h port; + rpc_port_h callback_port; + void *tag; + __callback_s callback; + void *user_data; +#ifdef TIDL_THREAD_ENABLE + GThread *thread; + GQueue *queue; + GMutex mutex; + GCond cond; + bool done; +#endif /* TIDL_THREAD_ENABLE */ +} __context_t; + +static bool ____exist_callback_port(rpc_port_h callback_port); +)__c_cb"; - __destroy_job(job); - return r; -} +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_DEF[] = +R"__c_cb( +typedef struct ___s { + rpc_port_parcelable_t parcelable; + rpc_port_h port; + int id; + int seq_id; + bool once; + bool valid; +} ___t; )__c_cb"; -const char CB_INTERFACE_ON_CONNECTED[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_BASE[] = R"__c_cb( -static void __##_on_connected(const char *sender, const char *instance, void *data) +static int ____context_handle_request(__context_h h, rpc_port_parcel_h parcel) { - rpc_port_stub_##_context_h context; + int ret = RPC_PORT_ERROR_NONE; + int cmd = -1; + + rpc_port_parcel_read_int32(parcel, &cmd); + if (cmd > 1 && cmd < ARRAY_SIZE(___method_table)) { + if (___method_table[cmd]) + ret = ___method_table[cmd](h->port, parcel, h); + } else { + _W("Invalid protocol. cmd(%d)", cmd); + ret = RPC_PORT_ERROR_INVALID_PARAMETER; + } + + return ret; +} - _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance); - context = __create_##_context(sender, instance); - if (!context) - return; +#ifdef TIDL_THREAD_ENABLE +static int ____context_push(__context_h h, rpc_port_parcel_h parcel) +{ + g_mutex_lock(&h->mutex); + g_queue_push_tail(h->queue, parcel); + g_cond_signal(&h->cond); + g_mutex_unlock(&h->mutex); - if (context->callback.create) - context->callback.create(context, context->user_data); - __##_contexts = g_list_append(__##_contexts, context); + return 0; } -)__c_cb"; -const char CB_INTERFACE_ON_DISCONNECTED[] = -R"__c_cb( -static void __##_on_disconnected(const char *sender, const char *instance, void *data) +static rpc_port_parcel_h ____context_wait_and_pop(__context_h h) { - rpc_port_stub_##_context_h context; + rpc_port_parcel_h parcel; - _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance); - context = __find_##_context(instance); - if (!context) - return; + g_mutex_lock(&h->mutex); + while (g_queue_is_empty(h->queue) && !h->done) + g_cond_wait(&h->cond, &h->mutex); - if (context->callback.terminate) - context->callback.terminate(context, context->user_data); - __##_contexts = g_list_remove(__##_contexts, context); - __destroy_##_context(context); + parcel = g_queue_pop_head(h->queue); + g_mutex_unlock(&h->mutex); + + return parcel; } -)__c_cb"; -const char CB_INTERFACE_ON_RECEIVED[] = -R"__c_cb( -static int __##_on_received(const char *sender, const char *instance, rpc_port_h port, void *data) +static gpointer ____context_thread_cb(gpointer user_data) { - rpc_port_stub_##_context_h context; - rpc_port_parcel_h parcel; - int cmd = -1; - int r; - - _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance); - context = __find_##_context(instance); - if (!context) { - _E("Failed to find ## context(%s)", instance); - return -1; + __context_h h = user_data; + rpc_port_parcel_h parcel; + + _W("START"); + while (!h->done) { + parcel = ____context_wait_and_pop(h); + if (parcel) { + ____context_handle_request(h, parcel); + rpc_port_parcel_destroy(parcel); } + } + _W("END"); - context->port = port; - r = rpc_port_parcel_create_from_port(&parcel, port); - if (r != 0) { - _E("Failed to create parcel from port"); - return r; - } + return nullptr; +} +#endif /* TIDL_THREAD_ENABLE */ - rpc_port_parcel_read_int32(parcel, &cmd); - if (cmd > 1 && cmd < (sizeof(__##_method_table) / sizeof(__##_method_table[0]))) { - if (__##_method_table[cmd]) - r = __##_method_table[cmd](port, parcel, context); - } else { - _E("Unknown Command(%d)", cmd); - r = -1; +static void ____context_destroy(gpointer data) +{ + __context_h h = data; +#ifdef TIDL_THREAD_ENABLE + rpc_port_parcel_h parcel; +#endif /* TIDL_THREAD_ENABLE */ + + if (h == nullptr) + return; + +#ifdef TIDL_THREAD_ENABLE + g_mutex_lock(&h->mutex); + h->done = true; + g_cond_signal(&h->cond); + g_mutex_unlock(&h->mutex); + + if (h->thread) { + g_thread_join(h->thread); + g_thread_unref(h->thread); + } + + g_mutex_clear(&h->mutex); + g_cond_clear(&h->cond); + + if (h->queue) { + while (!g_queue_is_empty(h->queue)) { + parcel = g_queue_pop_head(h->queue); + rpc_port_parcel_destroy(parcel); } - rpc_port_parcel_destroy(parcel); + g_queue_free(h->queue); + } +#endif /* TIDL_THREAD_ENABLE */ + + if (h->instance) + free(h->instance); - return r; + if (h->sender) + free(h->sender); + + free(h); } -)__c_cb"; -const char CB_INTERFACE_THREAD_ON_RECEIVED[] = -R"__c_cb( -static int __##_on_received(const char *sender, const char *instance, rpc_port_h port, void *data) +static __context_h ____context_create(const char *sender, const char *instance, rpc_port_h callback_port) { - rpc_port_stub_##_context_h context; - int r; + __context_t *handle; + + if (sender == nullptr || instance == nullptr || callback_port == nullptr) { + _E("Invalid parameter"); + return nullptr; + } + + handle = calloc(1, sizeof(__context_t)); + if (handle == nullptr) { + _E("Out of memory"); + return nullptr; + } + + handle->sender = strdup(sender); + if (handle->sender == nullptr) { + _E("Failed to duplicate sender"); + ____context_destroy(handle); + return nullptr; + } + + handle->instance = strdup(instance); + if (handle->instance == nullptr) { + _E("Failed to duplicate instance"); + ____context_destroy(handle); + return nullptr; + } + +#ifdef TIDL_THREAD_ENABLE + g_mutex_init(&handle->mutex); + g_cond_init(&handle->cond); + + handle->queue = g_queue_new(); + if (handle->queue == nullptr) { + _E("Failed to create queue"); + ____context_destroy(handle); + return nullptr; + } + + handle->thread = g_thread_new(instance, ____context_thread_cb, handle); + if (handle->thread == nullptr) { + _E("Failed to create thread"); + ____context_destroy(handle); + return nullptr; + } +#endif /* TIDL_THREAD_ENABLE */ + + handle->callback_port = callback_port; + handle->callback = __.callback; + handle->user_data = __.user_data; + + return handle; +} - _I("[__RPC_PORT__] sender(%s), instance(%s)", sender, instance); - context = __find_##_context(instance); - if (!context) { - _E("Failed to find ## context(%s)", instance); - return -1; - } - r = __add_thread_queue(port, context); +int __context_set_tag(__context_h context, void *tag) +{ + if (context == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - return r; + context->tag = tag; + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_THREAD_CREATE[] = -R"__c_cb( -__job_queue = g_queue_new(); -)__c_cb"; +int __context_get_tag(__context_h context, void **tag) +{ + if (context == nullptr || tag == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } -const char CB_INTERFACE_THREAD_DESTROY[] = -R"__c_cb( -while (!g_queue_is_empty(__job_queue)) { - job = g_queue_pop_head(__job_queue); - __destroy_job(job); + *tag = context->tag; + + return RPC_PORT_ERROR_NONE; } -g_queue_free(__job_queue); -__job_queue = NULL; -)__c_cb"; -const char CB_INTERFACE_REGISTER[] = -R"__c_cb( -int rpc_port_stub_##_register(rpc_port_stub_##_callback_s *callback, void *user_data) +int __context_get_sender(__context_h context, char **sender) { - int r; + char *value; - if (__##_stub) { - _W("Already exists"); - return -1; - } + if (context == nullptr || sender == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - if (!callback) { - _E("Invalid parameter"); - return -1; - } + value = strdup(context->sender); + if (value == nullptr) { + _E("Failed to duplicate sender"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } - __##_callback = *callback; - __##_user_data = user_data; - r = rpc_port_stub_create(&__##_stub, "##"); - if (r != 0) { - _E("Failed to create stub handle"); - return r; - } -$$ - - r = rpc_port_stub_add_received_event_cb(__##_stub, __##_on_received, NULL); - if (r != 0) { - _E("Failed to add received event callback"); - rpc_port_stub_destroy(__##_stub); - __##_stub = NULL; - return r; - } + *sender = value; - r = rpc_port_stub_add_connected_event_cb(__##_stub, __##_on_connected, NULL); - if (r != 0) { - _E("Failed to add connected event callback"); - rpc_port_stub_destroy(__##_stub); - __##_stub = NULL; - return r; - } + return RPC_PORT_ERROR_NONE; +} - r = rpc_port_stub_add_disconnected_event_cb(__##_stub, __##_on_disconnected, NULL); - if (r != 0) { - _E("Failed to add disconnected event callback"); - rpc_port_stub_destroy(__##_stub); - __##_stub = NULL; - return r; - } +int __context_get_instance(__context_h context, char **instance) +{ + char *value; - r = __##_add_privileges(); - if (r != 0) { - _E("Failed to add privileges"); - rpc_port_stub_destroy(__##_stub); - __##_stub = NULL; - return r; - } + if (context == nullptr || instance == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - r = rpc_port_stub_listen(__##_stub); - if (r != 0) { - _E("Failed to listen stub"); - rpc_port_stub_destroy(__##_stub); - __##_stub = NULL; - return r; - } + value = strdup(context->instance); + if (value == nullptr) { + _E("Failed to duplicate instance"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } - return 0; + *instance = value; + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_UNREGISTER[] = -R"__c_cb( -int rpc_port_stub_##_unregister(void) +static __context_h ____find_context(const char *instance) { - int r; -$$ - - if (!__##_stub) - return -1; - - if (__##_contexts) { - g_list_free_full(__##_contexts, __destroy_##_context); - __##_contexts = NULL; + __context_h context; + GList *iter; + + g_rec_mutex_lock(&__.mutex); + iter = __.contexts; + while (iter) { + context = iter->data; + if (!strcmp(context->instance, instance)) { + g_rec_mutex_unlock(&__.mutex); + return context; } - r = rpc_port_stub_destroy(__##_stub); - __##_stub = NULL; -$$ + iter = g_list_next(iter); + } + g_rec_mutex_unlock(&__.mutex); - return r; + return nullptr; } -)__c_cb"; -const char CB_INTERFACE_CLIENT_NUMBER_GETTER[] = -R"__c_cb( -int rpc_port_stub_##_get_client_number(unsigned int *n) +static void ____add_context(__context_h context) { - if (!n) { - _E("Invalid parameter"); - return -1; - } + g_rec_mutex_lock(&__.mutex); + __.contexts = g_list_append(__.contexts, context); + g_rec_mutex_unlock(&__.mutex); +} + +static void ____remove_context(__context_h context) +{ + g_rec_mutex_lock(&__.mutex); + __.contexts = g_list_remove(__.contexts, context); + g_rec_mutex_unlock(&__.mutex); +} - if (!__##_stub) { - _E("## Stub is not ready"); - return -1; +static bool ____exist_callback_port(rpc_port_h callback_port) +{ + rpc_port_h port; + GList *iter; + + g_rec_mutex_lock(&__.mutex); + iter = __.callback_ports; + while (iter) { + port = iter->data; + if (port == callback_port) { + g_rec_mutex_unlock(&__.mutex); + return true; } - *n = g_list_length(__##_contexts); + iter = g_list_next(iter); + } + g_rec_mutex_unlock(&__.mutex); - return 0; + return false; } -)__c_cb"; -const char CB_GLOBALS[] = -R"__c_cb( -static rpc_port_stub_h __##_stub; -static rpc_port_stub_##_callback_s __##_callback; -static void *__##_user_data; -static GList *__##_contexts; -)__c_cb"; +static void ____add_callback_port(rpc_port_h callback_port) +{ + g_rec_mutex_lock(&__.mutex); + __.callback_ports = g_list_append(__.callback_ports, callback_port); + g_rec_mutex_unlock(&__.mutex); +} -const char CB_INTERFACE_DELEGATOR_DECL[] = -R"__c_cb( -struct $$_s { - rpc_port_parcelable_t parcelable; - rpc_port_h port; - int id; - int seq_id; - bool once; - bool valid; -}; +static void ____remove_callback_port(rpc_port_h callback_port) +{ + g_rec_mutex_lock(&__.mutex); + __.callback_ports = g_list_remove(__.callback_ports, callback_port); + g_rec_mutex_unlock(&__.mutex); +} )__c_cb"; -const char CB_INTERFACE_DELEGATOR_CTOR[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + * The parameters of the delegate. + * The implementation to check whether arguments are nullptr or not + * The enumeration value of the method. + * The implementation to write arguments to the parcel. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE[] = R"__c_cb( -static int rpc_port_##_create(rpc_port_##_h *h) +static void _____to(rpc_port_parcel_h parcel, void *user_data) { - struct ##_s *handle; - static int seq_num; + ___h h = user_data; - if (!h) { - _E("Invalid parameter"); - return -1; - } + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + return; + } - handle = calloc(1, sizeof(struct ##_s)); - if (!handle) { - _E("Out of memory"); - return -1; - } + rpc_port_parcel_write_int32(parcel, h->id); - handle->parcelable.to = __##_to; - handle->parcelable.from = __##_from; - handle->id = $$_DELEGATE_$$; - handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1; - handle->once = false; - handle->valid = true; + rpc_port_parcel_write_int32(parcel, h->seq_id); - *h = handle; + rpc_port_parcel_write_bool(parcel, h->once); - return 0; + _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); } -)__c_cb"; -const char CB_INTERFACE_DELEGATOR_DTOR[] = -R"__c_cb( -int rpc_port_##_destroy(rpc_port_##_h h) +static void _____from(rpc_port_parcel_h parcel, void *user_data) { - if (!h) { - _E("Invalid parameter"); - return -1; - } + ___h h = user_data; - free(h); + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } - return 0; -} -)__c_cb"; + rpc_port_parcel_read_int32(parcel, &h->id); -const char CB_INTERFACE_DELEGATOR_SERIALIZER[] = -R"__c_cb( -static void __##_to(rpc_port_parcel_h parcel, void *data) -{ - rpc_port_##_h handle = data; + rpc_port_parcel_read_int32(parcel, &h->seq_id); - if (!handle) { - _E("Invalid parameter"); - return; - } + rpc_port_parcel_read_bool(parcel, &h->once); - rpc_port_parcel_write_int32(parcel, handle->id); - rpc_port_parcel_write_int32(parcel, handle->seq_id); - rpc_port_parcel_write_bool(parcel, handle->once); - _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false"); + _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); + set_last_result(RPC_PORT_ERROR_NONE); } -)__c_cb"; -const char CB_INTERFACE_DELEGATOR_DESERIALIZER[] = -R"__c_cb( -static void __##_from(rpc_port_parcel_h parcel, void *data) +int ___create(___h *h) { - rpc_port_##_h handle = data; + ___t *handle; + static int seq_num; + + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + handle = calloc(1, sizeof(___t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + handle->parcelable.to = _____to; + handle->parcelable.from = _____from; + handle->id = ; + handle->seq_id = g_atomic_int_add(&seq_num, 1) + 1; + handle->once = false; + handle->valid = true; + _I("id(%d), seq_id(%d)", handle->id, handle->seq_id); + + *h = handle; + + return RPC_PORT_ERROR_NONE; +} - if (!handle) { - _E("Invalid parameter"); - return; - } +int ___destroy(___h h) +{ + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + _W("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); - rpc_port_parcel_read_int32(parcel, &handle->id); - rpc_port_parcel_read_int32(parcel, &handle->seq_id); - rpc_port_parcel_read_bool(parcel, &handle->once); - _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false"); + free(h); + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_DELEGATOR_CLONER[] = -R"__c_cb( -int rpc_port_##_clone(rpc_port_##_h h, rpc_port_##_h *clone) +int ___clone(___h h, ___h *clone) { - rpc_port_##_h handle; + ___h handle; + int ret; - if (!h || !clone) { - _E("Invalid parameter"); - return -1; - } + if (h == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - handle = calloc(1, sizeof(struct ##_s)); - if (!handle) { - _E("Out of memory"); - return -1; - } + ret = ___create(&handle); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret); + return ret; + } - handle->parcelable = h->parcelable; - handle->port = h->port; - handle->id = h->id; - handle->seq_id = h->seq_id; - handle->once = h->once; - handle->valid = h->valid; - _I("id(%d), seq_id(%d), once(%s)", handle->id, handle->seq_id, handle->once ? "true" : "false"); + handle->port = h->port; + handle->seq_id = h->seq_id; + handle->once = h->once; + handle->valid = h->valid; - *clone = handle; + *clone = handle; - return 0; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_DELEGATOR_INVOKER[] = -R"__c_cb( -int rpc_port_$$_invoke($$) +int ___get_id(___h h, int *id) { - rpc_port_parcel_h parcel = NULL; - int r; + if (h == nullptr || id == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - if (!h || !h->port) { - _E("Invalid parameter"); - return -1; - } + *id = h->id; - if (h->once && !h->valid) { - _E("Invalid callback"); - return -1; - } + return RPC_PORT_ERROR_NONE; +} - rpc_port_parcel_create(&parcel); - if (!parcel) { - _E("Failed to create parcel"); - return -1; - } +int ___get_seq_id(___h h, int *seq_id) +{ + if (h == nullptr || seq_id == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - rpc_port_parcel_write_int32(parcel, $$_METHOD_Callback); - rpc_port_parcel_write(parcel, &h->parcelable, h); -$$ - r = rpc_port_parcel_send(parcel, h->port); - rpc_port_parcel_destroy(parcel); - h->valid = false; + *seq_id = h->seq_id; - return r; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_DELEGATOR_PORT_SETTER[] = -R"__c_cb( -int rpc_port_##_set_port(rpc_port_##_h h, rpc_port_h port) +int ___is_once(___h h, bool *once) { - if (!h || !port) { - _E("Invalid parameter"); - return -1; - } + if (h == nullptr || once == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - h->port = port; + *once = h->once; - return 0; + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_INTERFACE_CONTEXT_DECL[] = -R"__c_cb( -struct ##_context_s { - char *sender; - char *instance; - rpc_port_h port; - void *tag; - rpc_port_stub_##_callback_s callback; - void *user_data; -$$ -}; -)__c_cb"; +int ___get_tag(___h h, char **tag) +{ + char *value; + char buf[128]; -const char CB_INTERFACE_CONTEXT_DECL_THREAD_ELEM[] = -R"__c_cb(pthread_mutex_t mutex; -pthread_cond_t cond; -pthread_t thread; -bool run_wait_queue; -)__c_cb"; + if (h == nullptr || tag == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } -const char CB_INTERFACE_THREAD_FEATURE[] = -R"__c_cb( -typedef struct { - rpc_port_parcel_h parcel; - rpc_port_h port; - void *context; -} job_s; -typedef job_s *job_h; + snprintf(buf, sizeof(buf), "%d::%d", h->id, h->seq_id); + value = strdup(buf); + if (value == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } -static GQueue *__job_queue; + *tag = value; -static int __run_pending_job(void); + return RPC_PORT_ERROR_NONE; +} -static void *__wait_queue(void *data) +int ___set_port(___h h, rpc_port_h port) { - rpc_port_stub_##_context_h context = (rpc_port_stub_##_context_h)data; + if (h == nullptr || port == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - while(context->run_wait_queue) { - pthread_mutex_lock(&context->mutex); - pthread_cond_wait(&context->cond, &context->mutex); - __run_pending_job(); - pthread_mutex_unlock(&context->mutex); - } + h->port = port; - return NULL; + return RPC_PORT_ERROR_NONE; } -static job_h __create_job(rpc_port_parcel_h parcel, rpc_port_h port, void *context) +int ___invoke(___h h) { - job_h job; + rpc_port_parcel_h parcel_; + int ret_; - job = (job_s *)calloc(1, sizeof(job_s)); - if (!job) { - _E("Out of memory"); - return NULL; - } + if (h == nullptr || h->port == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - job->parcel = parcel; - job->port = port; - job->context = context; + if (!____exist_callback_port(h->port)) { + _E("Not connected"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } - return job; -} + if (h->once && !h->valid) { + _E("The delegate handle is already used"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } -static void __destroy_job(job_h job) -{ - rpc_port_parcel_destroy(job->parcel); - free(job); + ret_ = rpc_port_parcel_create(&parcel_); + if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret_); + return ret_; + } + + rpc_port_parcel_write_int32(parcel_, ); + + rpc_port_parcel_write(parcel_, &h->parcelable, h); + + + ret_ = rpc_port_parcel_send(parcel_, h->port); + rpc_port_parcel_destroy(parcel_); + h->valid = false; + + return ret_; } +)__c_cb"; -static int __add_thread_queue(rpc_port_h port, rpc_port_stub_##_context_h context) +/** + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_USER_DEFINED_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write(parcel_, &->parcelable, ); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_BUNDLE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_bundle(parcel_, ); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel_, ); +)__c_cb"; + +/** + * The type of the parcel. + * The argument. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_(parcel_, ); +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + * The method name of the interface. + * The declarations for arguments of the method. + * The implementation to read the parameter from the parcel. + * The implementation to invoke the callback function of the method. + * The implementation to write the result to the parcel. + * The implementation to release arguments. + */ +constexpr const char CB_INTERFACE_METHOD_HANDLER_BASE[] = +R"__c_cb( +static int ____method__handler(rpc_port_h port, rpc_port_parcel_h parcel, void *user_data) { - rpc_port_parcel_h parcel; - job_h job; - int r; + __context_h context_ = user_data; + rpc_port_h callback_port_; + int ret_; + - r = rpc_port_parcel_create_from_port(&parcel, port); - if (r != 0) { - _E("Failed to create parcel from port"); - return r; - } + ret_ = rpc_port_stub_get_port(__.stub, RPC_PORT_PORT_CALLBACK, context_->instance, &callback_port_); + if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to get callback port. error(%d)", ret_); + goto out; + } - job = __create_job(parcel, port, context); - g_queue_push_tail(__job_queue, job); - if (g_queue_is_empty(__job_queue)) { - _E("Empty queue ##"); - return -1; - } + + + - pthread_mutex_lock(&context->mutex); - pthread_cond_signal(&context->cond); - pthread_mutex_unlock(&context->mutex); +out: + - return 0; + return ret_; } )__c_cb"; -const char CB_INTERFACE_CONTEXT_CTOR[] = +/** + * The argument. + * The prefix of the interface. + * The name of the interface + */ +constexpr const char CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ[] = R"__c_cb( -static struct ##_context_s *__create_##_context(const char *sender, const char *instance) -{ - struct ##_context_s *handle; +ret_ = __create(&); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret_); + goto out; +} - handle = calloc(1, sizeof(struct ##_context_s)); - if (!handle) { - _E("Out of memory"); - return NULL; - } +__set_port(, callback_port_); +rpc_port_parcel_read(parcel, &->parcelable, ); +ret_ = get_last_result(); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", ret_); + goto out; +} +)__c_cb"; - handle->sender = strdup(sender); - if (!handle->sender) { - _E("Out of memory"); - free(handle); - return NULL; - } +/** + * The name of the value. + * The prefix of the structure. + * The name of the structure. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ[] = +R"__c_cb( +ret_ = __create(&); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret_); + goto out; +} - handle->instance = strdup(instance); - if (!handle->instance) { - _E("Out of memory"); - free(handle->sender); - free(handle); - return NULL; - } +rpc_port_parcel_read(parcel, &->parcelable, ); +ret_ = get_last_result(); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read data. error(%d)", ret_); + goto out; +} +)__c_cb"; - handle->callback = __##_callback; - handle->user_data = __##_user_data; -$$ - return handle; +/** + * The name of the value. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_bundle(parcel, &); +if ( == nullptr) { + _E("Failed to read data"); + ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + goto out; } )__c_cb"; -const char CB_INTERFACE_CONTEXT_CTOR_THREAD_IMPL[] = +/** + * The name of the value. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] = R"__c_cb( -pthread_mutex_init(&handle->mutex, NULL); -pthread_cond_init(&handle->cond, NULL); -handle->run_wait_queue = true; -if (pthread_create(&handle->thread, NULL, &__wait_queue, (void *)handle) < 0) { - _E("Fail to create thread"); - free(handle->instance); - free(handle->sender); - free(handle); - return NULL; +rpc_port_parcel_read_string(parcel, &); +if ( == nullptr) { + _E("Failed to read data"); + ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + goto out; } )__c_cb"; -const char CB_INTERFACE_CONTEXT_DTOR[] = +/** + * The type of the parcel. + * The name of the value. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_READ[] = R"__c_cb( -static void __destroy_##_context(gpointer data) -{ - struct ##_context_s *handle = data; -$$ - if (!handle) { - _E("Critical error!"); - return; - } +rpc_port_parcel_read_(parcel, &); +)__c_cb"; - free(handle->instance); - free(handle->sender); -$$ - free(handle); +/** + * The implemention to set the result of the callback function. + * The name of the method of the interface. + * The arguments of the method. + */ +constexpr const char CB_INTERFACE_METHOD_CALLBACK_INVOKE[] = +R"__c_cb( +if (context_->callback.) + context_->callback.(context_, context_->user_data); +)__c_cb"; + +/** + * The uppercase name of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_PARCEL_WRITE_PRE[] = +R"__c_cb( +ret_ = rpc_port_parcel_create(&parcel_); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret_); + goto out; } + +rpc_port_parcel_write_int32(parcel_, RPC_PORT_STUB__METHOD_RESULT_); +)__c_cb"; + +constexpr const char CB_INTERFACE_METHOD_PARCEL_WRITE_POST[] = +R"__c_cb( +ret_ = rpc_port_parcel_send(parcel_, port); +rpc_port_parcel_destroy(parcel_); )__c_cb"; -const char CB_INTERFACE_CONTEXT_DTOR_THREAD_VARS[] = -R"__c_cb(void *retval = NULL; -int ret; +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write(parcel_, &->parcelable, ); )__c_cb"; -const char CB_INTERFACE_CONTEXT_DTOR_THREAD_IMPL[] = +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE[] = R"__c_cb( -handle->run_wait_queue = false; -pthread_mutex_lock(&handle->mutex); -pthread_cond_signal(&handle->cond); -pthread_mutex_unlock(&handle->mutex); +rpc_port_parcel_write_bundle(parcel_, ); +)__c_cb"; -ret = pthread_join(handle->thread, &retval); -if (ret != 0) - _E("joining thread error [%d].", ret); +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel_, ); +)__c_cb"; -pthread_cond_destroy(&handle->cond); -pthread_mutex_destroy(&handle->mutex); +/** + * The type of the parcel. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_(parcel_, ); )__c_cb"; -const char CB_INTERFACE_CONTEXT_FINDER[] = +/** + * The argument. + * The prefix of the structure. + * The name of the structure. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_FREE[] = R"__c_cb( -static struct ##_context_s *__find_##_context(const char *instance) -{ - struct ##_context_s *handle; - GList *iter; +if () + __destroy(); +)__c_cb"; - iter = __##_contexts; - while (iter) { - handle = (struct ##_context_s *)iter->data; - if (!strcmp(handle->instance, instance)) - return handle; - iter = g_list_next(iter); - } +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_FREE[] = +R"__c_cb( +if () + bundle_free(); +)__c_cb"; - return NULL; -} +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_FREE[] = +R"__c_cb( +if () + free(); )__c_cb"; -const char CB_INTERFACE_CONTEXT_TAG_SETTER[] = +/** + * The name of the interface. + * The declarations of method handlers. + */ +constexpr const char CB_INTERFACE_METHOD_TABLE[] = R"__c_cb( -int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void *tag) +static rpc_port_stub_method_handler ___method_table[] = { + +}; +)__c_cb"; + +/** + * The enumeration value of the method. + * The prefix of the interface. + * The name of the interface. + * The method name of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_HANDLER[] = +R"__c_cb( +[] = ____method__handler, +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + * The implmentation to set the access control the stub handle. + */ +constexpr const char CB_INTERFACE_BASE[] = +R"__c_cb( +static void ____connected_event_cb(const char *sender, const char *instance, void *user_data) { - if (!ctx) { - _E("Invalid parameter"); - return -1; - } + __context_h context; + rpc_port_h callback_port = nullptr; + int ret; + + _W("sender(%s), instance(%s)", sender, instance); + ret = rpc_port_stub_get_port(__.stub, RPC_PORT_PORT_CALLBACK, instance, &callback_port); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to get callback port. error(%d)", ret); + return; + } + + context = ____context_create(sender, instance, callback_port); + if (context == nullptr) + return; + + ____add_context(context); + ____add_callback_port(context->callback_port); + context->callback.create(context, context->user_data); +} + +static void ____disconnected_event_cb(const char *sender, const char *instance, void *user_data) +{ + __context_h context; + - ctx->tag = tag; + _W("sender(%s), instance(%s)", sender, instance); + context = ____find_context(instance); + if (context == nullptr) + return; - return 0; + ____remove_callback_port(context->callback_port); + context->callback.terminate(context, context->user_data); + ____remove_context(context); + ____context_destroy(context); } -)__c_cb"; -const char CB_INTERFACE_CONTEXT_TAG_GETTER[] = -R"__c_cb( -int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void **tag) +static int ____received_event_cb(const char *sender, const char *instance, rpc_port_h port, void *user_data) { - if (!ctx || !tag) { - _E("Invalid parameter"); - return -1; - } + __context_h context; + rpc_port_parcel_h parcel; + int ret; + + _W("sender(%s), instance(%s)", sender, instance); + context = ____find_context(instance); + if (context == nullptr) { + _E("Failed to find context. instance(%s)", instance); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + context->port = port; + ret = rpc_port_parcel_create_from_port(&parcel, port); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle from port. error(%d)", ret); + return ret; + } + +#ifdef TIDL_THREAD_ENABLE + ret = ____context_push(context, parcel); +#else + ret = ____context_handle_request(context, parcel); + rpc_port_parcel_destroy(parcel); +#endif /* TIDL_THREAD_ENABLE */ + + return ret; +} - *tag = ctx->tag; +static int ____set_access_control(void) +{ + int ret = RPC_PORT_ERROR_NONE; + + - return 0; + return ret; } -)__c_cb"; -const char CB_INTERFACE_CONTEXT_GET_SENDER[] = -R"__c_cb( -int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char **sender) +int __register(rpc_port_stub__callback_s *callback, void *user_data) { - if (!ctx || !sender) { - _E("Invalid parameter"); - return -1; - } + int ret; + + if (callback == nullptr || callback->create == nullptr || callback->terminate == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + if (__.stub) { + _E("Already exists"); + return RPC_PORT_ERROR_NONE; + } + + g_rec_mutex_init(&__.mutex); + __.callback = *callback; + __.user_data = user_data; + + ret = rpc_port_stub_create(&__.stub, ""); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to create stub handle. error(%d)", ret); + __unregister(); + return ret; + } + + ret = rpc_port_stub_add_received_event_cb(__.stub, ____received_event_cb, &__); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add received event callback"); + __unregister(); + return ret; + } + + ret = rpc_port_stub_add_connected_event_cb(__.stub, ____connected_event_cb, &__); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add connected event callback"); + __unregister(); + return ret; + } + + ret = rpc_port_stub_add_disconnected_event_cb(__.stub, ____disconnected_event_cb, &__); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add disconnected event callback"); + __unregister(); + return ret; + } + + ret = ____set_access_control(); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add privileges"); + __unregister(); + return ret; + } + + ret = rpc_port_stub_listen(__.stub); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to listen events. error(%d)", ret); + __unregister(); + return ret; + } + + return RPC_PORT_ERROR_NONE; +} - *sender = strdup(ctx->sender); - if (*sender == NULL) { - _E("Out of memory"); - return -1; - } +int __unregister(void) +{ + g_rec_mutex_lock(&__.mutex); + g_rec_mutex_unlock(&__.mutex); + g_rec_mutex_clear(&__.mutex); - return 0; + if (__.contexts) { + g_list_free_full(__.contexts, ____context_destroy); + __.contexts = nullptr; + } + + if (__.stub) { + rpc_port_stub_destroy(__.stub); + __.stub = nullptr; + } + + return RPC_PORT_ERROR_NONE; } -)__c_cb"; -const char CB_STUB_METHOD_TYPE[] = -R"__c_cb( -typedef int (*stub_method)(rpc_port_h, rpc_port_parcel_h, void *data); -)__c_cb"; +int __foreach_context(__context_cb callback, void *user_data) +{ + __context_h context; + GList *iter; + + if (callback == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + g_rec_mutex_lock(&__.mutex); + iter = __.contexts; + while (iter) { + context = iter->data; + if (!callback(context, user_data)) + break; + + iter = g_list_next(iter); + } + g_rec_mutex_unlock(&__.mutex); + + return RPC_PORT_ERROR_NONE; +} -const char CB_INTERFACE_ADD_PRIVILEGE[] = -R"__c_cb( -static int __$$_add_privileges(void) +int __get_client_number(unsigned int *client_number) { -$$ - return 0; + if (client_number == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + if (__.stub == nullptr) { + _E("Invalid context"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + g_rec_mutex_lock(&__.mutex); + *client_number = g_list_length(__.contexts); + g_rec_mutex_unlock(&__.mutex); + + return RPC_PORT_ERROR_NONE; } )__c_cb"; -const char CB_INTERFACE_PRIVILEGE_BLOCK[] = -R"__c_cb(r = $$; -if (r != 0) { - _E("Failed to add privilege($$)"); - return r; +/** + * The name of the interface. + * The privilege name. + */ +constexpr const char CB_INTERFACE_PRIVILEGE_ADD[] = +R"__c_cb( +ret = rpc_port_stub_add_privilege(__.stub, ""); +if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to add privilege. error(%d)", ret); + return ret; } )__c_cb"; -const char CB_INTERFACE_TRUSTED_MODE_BLOCK[] = -R"__c_cb(r = $$; -if (r != 0) { - _E("Failed to set trusted mode($$)"); - return r; +/** + * The name of the interface. + */ +constexpr const char CB_INTERFACE_TRUSTED_SET[] = +R"__c_cb( +ret = rpc_port_stub_set_trusted(__.stub, true); +if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to set trusted mode. error(%d)", ret); + return ret; } )__c_cb"; diff --git a/idlc/gen/c_stub_header_gen.cc b/idlc/gen/c_stub_header_gen.cc index 426cd6d7..8d9b4a05 100644 --- a/idlc/gen/c_stub_header_gen.cc +++ b/idlc/gen/c_stub_header_gen.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,10 @@ void CStubHeaderGen::OnInitGen(std::ofstream& stream) { GenPragmaOnce(stream); GenIncludeDefaultHeaders(stream, false); GenExplicitLinkageOpen(stream); + GenStructureHandles(stream); + GenInterfaceHandles(stream); GenStructures(stream); + GenInterfaceCallbacks(stream); GenInterfaces(stream); } @@ -38,6 +41,96 @@ void CStubHeaderGen::OnFiniGen(std::ofstream& stream) { GenExplicitLinkageClose(stream); } +void CStubHeaderGen::GenInterfaceHandles(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& inf = static_cast(*b); + GenInterfaceContextHandle(stream, inf); + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateHandle(stream, inf, *d); + } + } +} + +// @see #CB_INTERFACE_CONTEXT_HANDLE +void CStubHeaderGen::GenInterfaceContextHandle(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_HANDLE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_DELEGATE_HANDLE +void CStubHeaderGen::GenInterfaceDelegateHandle(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_HANDLE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + + stream << SmartIndent(code); +} + +void CStubHeaderGen::GenInterfaceCallbacks(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& inf = static_cast(*b); + GenInterfaceCallbackBase(stream, inf); + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceMethodCallbackBase(stream, inf, *d); + } + } +} + +// @see #CB_INTERFACE_CALLBACK_BASE +void CStubHeaderGen::GenInterfaceCallbackBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_CALLBACK_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + + stream << SmartIndent(code); +} + +std::string CStubHeaderGen::GenMethodParams(const Interface& inf, + const Declaration& decl) { + std::string params; + for (auto& p : decl.GetParameters().GetParams()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, inf) + + p->GetID(); + } + + return params; +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_BASE +void CStubHeaderGen::GenInterfaceMethodCallbackBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_BASE, + "", GetReturnTypeString(decl.GetType())); + code = ReplaceAll(code, "", GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + code = ReplaceAll(code, "", GenMethodParams(inf, decl)); + + stream << SmartIndent(code); +} + void CStubHeaderGen::GenInterfaces(std::ofstream& stream) { for (auto& i : GetDocument().GetBlocks()) { if (i->GetType() != Block::TYPE_INTERFACE) @@ -49,156 +142,85 @@ void CStubHeaderGen::GenInterfaces(std::ofstream& stream) { } void CStubHeaderGen::GenInterface(std::ofstream& stream, - const Interface& inf) { - GenInterfaceContext(stream, inf); - GenInterfaceDelegators(stream, inf); - GenInterfaceDeclaration(stream, inf); - GenInterfaceRegister(stream, inf); - GenInterfaceUnregister(stream, inf); - GenInterfaceClientNumberGetter(stream, inf); -} - -void CStubHeaderGen::GenInterfaceDeclaration(std::ofstream& stream, - const Interface& inf) { - stream << SmartIndent(GenTemplateString(ReplaceAll( - CB_INTERFACE_DECL, "##", GetInterfaceIdWithNamespace(inf)), - [&]()->std::string { - std::string str; - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() == Declaration::MethodType::DELEGATE) - continue; - str += NLine(1); - str += GenTemplateString(CB_INTERFACE_CALLBACK, - [&]()->std::string { - return GetReturnTypeString(i->GetType()); - }, - [&]()->std::string { - return i->GetID(); - }, - [&]()->std::string { - return GetInterfaceIdWithNamespace(inf); - }, - [&]()->std::string { - std::string s; - for (auto& p : i->GetParameters().GetParams()) { - if (IsDelegateType(inf, p->GetParameterType() - .GetBaseType())) { - s += "rpc_port_" + GetInterfaceIdWithNamespace(inf) - + "_" + p->GetParameterType().GetBaseType().ToString() - + "_h " + p->GetID(); - } else { - s += GetParamTypeString(p->GetParameterType() - .GetDirection(), p->GetParameterType().GetBaseType()) - + p->GetID(); - } - s += ", "; - } - return s; - }); - } - return str; - })); -} - -void CStubHeaderGen::GenInterfaceContext(std::ofstream& stream, - const Interface& inf) { - GenInterfaceContextDeclaration(stream, inf); - GenInterfaceContextTagSetter(stream, inf); - GenInterfaceContextTagGetter(stream, inf); - GenInterfaceContextSenderGetter(stream, inf); -} - -void CStubHeaderGen::GenInterfaceContextDeclaration( - std::ofstream& stream, const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CONTEXT_DECL, "##", - GetInterfaceIdWithNamespace(inf)); -} - -void CStubHeaderGen::GenInterfaceContextTagSetter( - std::ofstream& stream, const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CONTEXT_SET_TAG, "##", - GetInterfaceIdWithNamespace(inf)); -} - -void CStubHeaderGen::GenInterfaceContextTagGetter( - std::ofstream& stream, const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CONTEXT_GET_TAG, "##", - GetInterfaceIdWithNamespace(inf)); -} - -void CStubHeaderGen::GenInterfaceContextSenderGetter( - std::ofstream& stream, const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CONTEXT_GET_SENDER, "##", - GetInterfaceIdWithNamespace(inf)); -} - -void CStubHeaderGen::GenInterfaceDelegators(std::ofstream& stream, - const Interface& inf) { - for (auto& i : inf.GetDeclarations().GetDecls()) { - if (i->GetMethodType() != Declaration::MethodType::DELEGATE) + const Interface& inf) { + GenInterfaceContextBase(stream, inf); + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) continue; - GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i); + + GenInterfaceDelegateBase(stream, inf, *d); } -} -void CStubHeaderGen::GenInterfaceDelegator(std::ofstream& stream, - const std::string& id, - const Declaration& decl) { - GenInterfaceDelegatorDeclaration(stream, id, decl); - GenInterfaceDelegatorDestructor(stream, id, decl); - GenInterfaceDelegatorCloner(stream, id, decl); - GenInterfaceDelegatorInvoker(stream, id, decl); + GenInterfaceBase(stream, inf); } -void CStubHeaderGen::GenInterfaceDelegatorDeclaration( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << ReplaceAll( - CB_INTERFACE_DELEGATOR_DECL, "##", id + "_" + decl.GetID()); -} +// @see #CB_INTERFACE_CONTEXT_BASE +void CStubHeaderGen::GenInterfaceContextBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_CONTEXT_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); -void CStubHeaderGen::GenInterfaceDelegatorDestructor( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << ReplaceAll( - CB_INTERFACE_DELEGATOR_DTOR, "##", id + "_" + decl.GetID()); + stream << SmartIndent(code); } -void CStubHeaderGen::GenInterfaceDelegatorCloner( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << ReplaceAll( - CB_INTERFACE_DELEGATOR_CLONER, "##", id + "_" + decl.GetID()); -} +std::string CStubHeaderGen::GenDelegateParams(const Interface& inf, + const Declaration& decl) { + std::string params; + for (auto& p : decl.GetParameters().GetParams()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, inf) + + p->GetID(); + } -void CStubHeaderGen::GenInterfaceDelegatorInvoker( - std::ofstream& stream, const std::string& id, const Declaration& decl) { - stream << GenTemplateString(ReplaceAll( - CB_INTERFACE_DELEGATOR_INVOKER, "##", id + "_" + decl.GetID()), - [&]()->std::string { - std::string str; - for (auto& i : decl.GetParameters().GetParams()) { - str += ", "; - str += GetParamTypeString(i->GetParameterType().GetDirection(), - i->GetParameterType().GetBaseType()) + i->GetID(); - } - return str; - }); + return params; } -void CStubHeaderGen::GenInterfaceRegister(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_REGISTER, "##", - GetInterfaceIdWithNamespace(inf)); +// @see #CB_INTERFACE_DELEGATE_BASE +void CStubHeaderGen::GenInterfaceDelegateBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl) { + std::string code = ReplaceAll(CB_INTERFACE_DELEGATE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", decl.GetID()); + code = ReplaceAll(code, "", GenDelegateParams(inf, decl)); + + stream << SmartIndent(code); } -void CStubHeaderGen::GenInterfaceUnregister(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_UNREGISTER, "##", - GetInterfaceIdWithNamespace(inf)); +// @see #CB_INTERFACE_METHOD_CALLBACK_DECL +std::string CStubHeaderGen::GenMethodCallbackDecls(const Interface& inf) { + std::string method_callback_decls; + for (auto& d : inf.GetDeclarations().GetDecls()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + std::string method_callback_decl = ReplaceAll( + CB_INTERFACE_METHOD_CALLBACK_DECL, "", GetHandlePrefix()); + method_callback_decl = ReplaceAll(method_callback_decl, "", + inf.GetID()); + method_callback_decl = ReplaceAll(method_callback_decl, "", + d->GetID()); + + method_callback_decl = RemoveLine(method_callback_decl); + method_callback_decls += RemoveLine(method_callback_decl, 2); + } + + return method_callback_decls; } -void CStubHeaderGen::GenInterfaceClientNumberGetter(std::ofstream& stream, - const Interface& inf) { - stream << ReplaceAll(CB_INTERFACE_CLIENT_NUMBER_GETTER, "##", - GetInterfaceIdWithNamespace(inf)); +// @see #CB_INTERFACE_BASE +void CStubHeaderGen::GenInterfaceBase(std::ofstream& stream, + const Interface& inf) { + std::string code = ReplaceAll(CB_INTERFACE_BASE, "", + GetHandlePrefix()); + code = ReplaceAll(code, "", inf.GetID()); + code = ReplaceAll(code, "", + GenMethodCallbackDecls(inf)); + + stream << SmartIndent(code); } } // namespace tidl diff --git a/idlc/gen/c_stub_header_gen.h b/idlc/gen/c_stub_header_gen.h index 43d2e532..f7c9f4b0 100644 --- a/idlc/gen/c_stub_header_gen.h +++ b/idlc/gen/c_stub_header_gen.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,42 +33,27 @@ class CStubHeaderGen : public CHeaderGeneratorBase { void OnFiniGen(std::ofstream& stream) override; private: + void GenInterfaceHandles(std::ofstream& stream); + void GenInterfaceContextHandle(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + + void GenInterfaceCallbacks(std::ofstream& stream); + void GenInterfaceCallbackBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceMethodCallbackBase(std::ofstream& stream, + const Interface& inf, const Declaration& decl); + void GenInterfaces(std::ofstream& stream); void GenInterface(std::ofstream& stream, const Interface& inf); - void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf); - void GenInterfaceContext(std::ofstream& stream, const Interface& inf); - void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf); - void GenInterfaceRegister(std::ofstream& stream, const Interface& inf); - void GenInterfaceUnregister(std::ofstream& stream, const Interface& inf); - void GenInterfaceClientNumberGetter(std::ofstream& stream, - const Interface& inf); - private: - void GenInterfaceContextDeclaration(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextTagSetter(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextTagGetter(std::ofstream& stream, - const Interface& inf); - void GenInterfaceContextSenderGetter(std::ofstream& stream, - const Interface& inf); + void GenInterfaceContextBase(std::ofstream& stream, const Interface& inf); + void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& inf, + const Declaration& decl); + void GenInterfaceBase(std::ofstream& stream, const Interface& inf); - private: - void GenInterfaceDelegator(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDeclaration(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorDestructor(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorCloner(std::ofstream& stream, - const std::string& id, - const Declaration& decl); - void GenInterfaceDelegatorInvoker(std::ofstream& stream, - const std::string& id, - const Declaration& decl); + std::string GenDelegateParams(const Interface& inf, const Declaration& decl); + std::string GenMethodParams(const Interface& inf, const Declaration& decl); + std::string GenMethodCallbackDecls(const Interface& inf); }; } // namespace tidl diff --git a/idlc/gen/c_stub_header_gen_cb.h b/idlc/gen/c_stub_header_gen_cb.h index 49e37f08..d4e27f51 100644 --- a/idlc/gen/c_stub_header_gen_cb.h +++ b/idlc/gen/c_stub_header_gen_cb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,71 +17,341 @@ #ifndef IDLC_C_GEN_C_STUB_HEADER_GEN_CB_H_ #define IDLC_C_GEN_C_STUB_HEADER_GEN_CB_H_ -const char CB_INTERFACE_DECL[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_HANDLE[] = R"__c_cb( -typedef struct { - void (*create)(rpc_port_stub_##_context_h context, void *user_data); - void (*terminate)(rpc_port_stub_##_context_h context, void *user_data); -$$ -} rpc_port_stub_##_callback_s; +/** + * @brief The __context handle. + */ +typedef struct __context_s *__context_h; )__c_cb"; -const char CB_INTERFACE_CALLBACK[] = -R"__c_cb($$(*$$)(rpc_port_stub_$$_context_h context, $$void *user_data);)__c_cb"; - -const char CB_INTERFACE_CONTEXT_DECL[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_BASE[] = R"__c_cb( -typedef struct ##_context_s* rpc_port_stub_##_context_h; -)__c_cb"; +/** + * @brief Sets the tag to the context handle. + * + * @param[in] context The context handle + * @param[in] tag The tag + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @see __context_get_tag() + */ +int __context_set_tag(__context_h context, void *tag); -const char CB_INTERFACE_CONTEXT_SET_TAG[] = -R"__c_cb( -int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void *tag); -)__c_cb"; +/** + * @brief Gets the tag from the context handle. + * + * @param[in] context The context handle + * @param[out] tag The tag + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @see __context_set_tag() + */ +int __context_get_tag(__context_h context, void **tag); -const char CB_INTERFACE_CONTEXT_GET_TAG[] = -R"__c_cb( -int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void **tag); -)__c_cb"; +/** + * @brief Gets the sender ID from the context handle. + * @details The @a sender should be released using free(). + * + * @param[in] context The context handle + * @param[out] sender The sender ID of the context handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + */ +int __context_get_sender(__context_h context, char **sender); -const char CB_INTERFACE_CONTEXT_GET_SENDER[] = -R"__c_cb( -int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char **sender); +/** + * @brief Gets the instance ID from the context handle. + * @details The @a instance should be released using free(). + * + * @param[in] context The context handle + * @param[out] instance The instance ID of the context handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + */ +int __context_get_instance(__context_h context, char **instance); )__c_cb"; -const char CB_INTERFACE_DELEGATOR_DECL[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_HANDLE[] = R"__c_cb( -typedef struct ##_s *rpc_port_##_h; +/** + * @brief The __ handle. + */ +typedef struct ___s *___h; )__c_cb"; -const char CB_INTERFACE_DELEGATOR_DTOR[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the delegate. + * The parameters of the callback function. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE[] = R"__c_cb( -int rpc_port_##_destroy(rpc_port_##_h h); -)__c_cb"; +/** + * @brief Creates a __ handle. + * + * @param[out] h The __ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @see ___destroy() + */ +int ___create(___h *h); -const char CB_INTERFACE_DELEGATOR_CLONER[] = -R"__c_cb( -int rpc_port_##_clone(rpc_port_##_h h, rpc_port_##_h *clone); +/** + * @brief Destroys the __ handle. + * + * @param[in] h The __ 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 ___clone() + */ +int ___destroy(___h h); + +/** + * @brief Creates and returns a copy of the given __ handle. + * + * @remarks A new created __ should be released using + * the ___destroy() if it's no longer needed. + * @param[in] h The __ handle + * @param[out] clone If successful, a new created __ 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 ___destroy() + */ +int ___clone(___h h, ___h *clone); + +/** + * @brief Gets the ID of the __ handle. + * + * @param[in] h The __ handle + * @param[out] id The ID + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___get_id(___h h, int *id); + +/** + * @brief Gets the sequence ID of the __ handle. + * + * @param[in] h The __ handle + * @param[out] seq_id The Sequence ID + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___get_seq_id(___h h, int *seq_id); + +/** + * @brief Checks whether the delegate is for one-time or not. + * + * @param[in] h The __ handle + * @param[out] once The flag, it's true, the handle is for one-time + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int ___is_once(___h h, bool *once); + +/** + * @brief Gets the tag from the __ handle. + * + * @remarks The @a tag should be released using free(). + * @param[in] h The __ handle + * @param[out] tag The tag + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + */ +int ___get_tag(___h h, char **tag); + +/** + * @brief Invokes the callback function of the __ handle. + * + * @param[in] h The __ handle + * @param[in] ... + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @retval #RPC_PORT_ERROR_IO_ERROR I/O error + */ +int ___invoke(___h h); )__c_cb"; -const char CB_INTERFACE_DELEGATOR_INVOKER[] = +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CALLBACK_BASE[] = R"__c_cb( -int rpc_port_##_invoke(rpc_port_##_h h$$); +/** + * @brief Called when the proxy is connected. + * @details The callback function is called when the proxy is connected to the stub. + * + * @param[in] context The context handle + * @param[in] user_data The user data passed from the registration function + * @see #__callback_s + */ +typedef void (*__create_cb)(__context_h context, void *user_data); + +/** + * @brief Called when the proxy is disconnected. + * @details The callback function is called when the proxy is disconnected from the stub. + * + * @param[in] context The context handle + * @param[in] user_data The user data passed from the registration function + * @see #__callback_s + */ +typedef void (*__terminate_cb)(__context_h context, void *user_data); + +/** + * @brief Called to get the proxy context once for each connected proxy. + * + * @param[in] context The context handle + * @param[in] user_data The user data passed from the registration function + * @return @c true to continue with the next iteration of the loop, + * otherwise @c false to break out of the loop + * @pre __foreach_context() will invoke this callback. + * @see __foreach_context() + */ +typedef bool (*__context_cb)(__context_h context, void *user_data); )__c_cb"; -const char CB_INTERFACE_REGISTER[] = +/** + * The return type of the method. + * The prefix of the interface. + * The name of the interface. + * The name of the method of the interface. + * The parameters of the method. + */ +constexpr const char CB_INTERFACE_METHOD_CALLBACK_BASE[] = R"__c_cb( -int rpc_port_stub_##_register(rpc_port_stub_##_callback_s *callback, void *user_data); +/** + * @brief Called when the request of the proxy is delivered. + * + * @param[in] context The context handle + * @param[in] user_data The user data passed from the registration function + * @see #__callback_s; + */ +typedef (*___cb)(__context_h context, void *user_data); )__c_cb"; -const char CB_INTERFACE_UNREGISTER[] = +/** + * The prefix of the interface. + * The name of the interface. + * The declarations of the method callback functions. + */ +constexpr const char CB_INTERFACE_BASE[] = R"__c_cb( -int rpc_port_stub_##_unregister(void); +/** + * @brief The structure type containing the set of callback functions for handling stub events. + * @details It is one of the input parameters of the __register() function. + * + * @see __create_cb + * @see __terminate_cb + */ +typedef struct { + __create_cb create; /**< This callback function is invoked when the proxy is connected. */ + __terminate_cb terminate; /**< This callback function is invoked when the proxy is disconnected. */ + +} __callback_s; + +/** + * @brief Registers the set of the callback functions and the port. + * @details This function registers the set of the callback functions to handle stub events. + * And, the rpc_port_stub_listen() is called internally to handle events. + * + * @param[in] callback The set of callback functions to handle stub events + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @retval #RPC_PORT_ERROR_IO_ERROR I/O error + * @retval #RPC_PORT_ERROR_PERMISSION_DENIED Permission denied + * @see __unregister() + * @see #__callback_s + */ +int __register(__callback_s *callback, void *user_data); + +/** + * @brief Unregisters the registered port. + */ +int __unregister(void); + +/** + * @brief Retrieves the connected context handles. + * + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @see __context_cb() + */ +int __foreach_context(__context_cb callback, void *user_data); + +/** + * @brief Gets the number of connected clients. + * + * @param[out] client_number The client number + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + */ +int __get_client_number(unsigned int *client_number); )__c_cb"; -const char CB_INTERFACE_CLIENT_NUMBER_GETTER[] = +/** + * The prefix of the interface. + * The name of the interface. + * The name of the method of the interface. + */ +constexpr const char CB_INTERFACE_METHOD_CALLBACK_DECL[] = R"__c_cb( -int rpc_port_stub_##_get_client_number(unsigned int *n); +___cb ; /**< This callback function is invoked when the request is delivered. */ )__c_cb"; #endif // IDLC_C_GEN_C_STUB_HEADER_GEN_CB_H_ diff --git a/idlc/gen/generator.h b/idlc/gen/generator.h index 249b5948..a1706ed3 100644 --- a/idlc/gen/generator.h +++ b/idlc/gen/generator.h @@ -50,6 +50,14 @@ class Generator { return hasNamespace_; } + void EnableProxy(bool enable) { + isProxy_ = enable; + } + + bool IsProxy() const { + return isProxy_; + } + template void GenTemplate(std::string templ, std::ofstream& stream, T cb, ARGS... args) { @@ -113,6 +121,7 @@ class Generator { std::shared_ptr doc_; std::ofstream out_file_; bool hasNamespace_ = true; + bool isProxy_ = true; }; } // namespace tidl diff --git a/idlc/main.cc b/idlc/main.cc index 37f8aa13..206fc034 100644 --- a/idlc/main.cc +++ b/idlc/main.cc @@ -55,9 +55,11 @@ void GenerateStubCodes(std::shared_ptr options, { tidl::CStubHeaderGen stub_header(ps.GetDoc()); stub_header.EnableNamespace(options->HasNamespace()); + stub_header.EnableProxy(false); stub_header.Run(options->GetOutput() + ".h"); tidl::CStubBodyGen stub_body(ps.GetDoc(), options); stub_body.EnableNamespace(options->HasNamespace()); + stub_body.EnableProxy(false); stub_body.Run(options->GetOutput() + ".c"); break; } @@ -108,9 +110,11 @@ void GenerateProxyCodes(std::shared_ptr options, { tidl::CProxyHeaderGen proxy_header(ps.GetDoc()); proxy_header.EnableNamespace(options->HasNamespace()); + proxy_header.EnableProxy(true); proxy_header.Run(options->GetOutput() + ".h"); - tidl::CProxyBodyGen proxy_body(ps.GetDoc()); + tidl::CProxyBodyGen proxy_body(ps.GetDoc(), options); proxy_body.EnableNamespace(options->HasNamespace()); + proxy_body.EnableProxy(true); proxy_body.Run(options->GetOutput() + ".c"); break; }