From: jusung Date: Fri, 6 Jan 2023 05:15:32 +0000 (+0900) Subject: Implement C stub generator X-Git-Tag: accepted/tizen/unified/20230420.153149~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F40%2F286440%2F4;p=platform%2Fcore%2Fappfw%2Ftidl.git Implement C stub generator Change-Id: Ieb8d5243041323f782a114ea84a927cf5d24e5f1 Signed-off-by: jusung --- diff --git a/idlc/gen/version2/c_body_generator_base.cc b/idlc/gen/version2/c_body_generator_base.cc index 62404ff..6683217 100644 --- a/idlc/gen/version2/c_body_generator_base.cc +++ b/idlc/gen/version2/c_body_generator_base.cc @@ -479,14 +479,7 @@ void CBodyGeneratorBase::GenStructureBase(std::ofstream& stream, void CBodyGeneratorBase::AddParameterType(const Interface& iface, const BaseType& type, ParameterType::Direction direction) { if (IsDelegateType(iface, type)) { - AddParameterType( - std::make_shared( - new BaseType("delegate", "delegate", true), - ParameterType::Direction::IN)); - AddParameterType( - std::make_shared( - new BaseType("delegate", "delegate", true), - ParameterType::Direction::OUT)); + return; } else if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) { AddParameterType( std::make_shared( @@ -512,26 +505,11 @@ void CBodyGeneratorBase::AddParameterType( param_types_[key] = std::move(param_type); } -void CBodyGeneratorBase::GenDelegateDefinition(std::ofstream& stream) { - stream << SmartIndent(CB_DELEGATE_DEFS); -} - -void CBodyGeneratorBase::GenDelegateBase(std::ofstream& stream) { - stream << SmartIndent(CB_DELEGATE_BASE); -} - void CBodyGeneratorBase::GenUnitMapDefinition(std::ofstream& stream) { stream << SmartIndent(CB_UNIT_MAP_DEFS); } void CBodyGeneratorBase::GenParameterMap() { - if (GetChannelType() == ChannelType::TYPE_PROXY) { - AddParameterType( - std::make_shared( - new BaseType("delegate", "delegate", true), - ParameterType::Direction::OUT)); - } - AddParameterType( std::make_shared( new BaseType("int", "int"), ParameterType::Direction::IN)); @@ -554,17 +532,47 @@ void CBodyGeneratorBase::GenParameterMap() { for (const auto& decl : iface.GetDeclarations()) { for (const auto& param : decl->GetParameters()) { auto& type = param->GetParameterType().GetBaseType(); - AddParameterType(iface, type, + if (decl->GetMethodType() == Declaration::MethodType::DELEGATE) { + AddParameterType(iface, type, ParameterType::Direction::OUT); + } else { + AddParameterType(iface, type, param->GetParameterType().GetDirection()); + } } + auto& type = decl->GetType(); if (decl->GetMethodType() == Declaration::MethodType::SYNC) { - auto& type = decl->GetType(); AddParameterType(iface, type, ParameterType::Direction::OUT); + } else if (decl->GetMethodType() == Declaration::MethodType::DELEGATE) { + AddParameterType( + std::make_shared( + new BaseType("delegate", "delegate", true), + ParameterType::Direction::IN)); + AddParameterType( + std::make_shared( + new BaseType("delegate", "delegate", true), + ParameterType::Direction::OUT)); + AddParameterType( + std::make_shared( + new BaseType(iface.GetID() + "_" + decl->GetID(), "", true), + ParameterType::Direction::IN)); + AddParameterType( + std::make_shared( + new BaseType(iface.GetID() + "_" + decl->GetID(), "", true), + ParameterType::Direction::OUT)); } } } else { auto& st = static_cast(*block); + AddParameterType( + std::make_shared( + new BaseType(st.GetID(), st.GetID(), true), + ParameterType::Direction::IN)); + AddParameterType( + std::make_shared( + new BaseType(st.GetID(), st.GetID(), true), + ParameterType::Direction::OUT)); + for (auto& elm : st.GetElements()) { auto& type = elm->GetType(); AddParameterType( @@ -581,6 +589,9 @@ void CBodyGeneratorBase::GenParameterMap() { void CBodyGeneratorBase::GenUnitMapBase(std::ofstream& stream) { stream << SmartIndent(CB_UNIT_MAP_BASE); + if (GetChannelType() == ChannelType::TYPE_PROXY) + stream << SmartIndent(CB_UNIT_MAP_CLEAR_BASE); + GenParameterMap(); std::string code; diff --git a/idlc/gen/version2/c_body_generator_base.hh b/idlc/gen/version2/c_body_generator_base.hh index aaf4a71..34f6cad 100644 --- a/idlc/gen/version2/c_body_generator_base.hh +++ b/idlc/gen/version2/c_body_generator_base.hh @@ -33,7 +33,6 @@ class CBodyGeneratorBase : public tidl::CBodyGeneratorBase { void GenStructureDefinition(std::ofstream& stream); void GenStructure(std::ofstream& stream); - void GenDelegateDefinition(std::ofstream& stream); void GenDelegateBase(std::ofstream& stream); void GenUnitMapDefinition(std::ofstream& stream); void GenUnitMapBase(std::ofstream& stream); diff --git a/idlc/gen/version2/c_body_generator_base_cb.hh b/idlc/gen/version2/c_body_generator_base_cb.hh index 40eed5d..3ccf924 100644 --- a/idlc/gen/version2/c_body_generator_base_cb.hh +++ b/idlc/gen/version2/c_body_generator_base_cb.hh @@ -20,88 +20,6 @@ namespace tidl { namespace version2 { -constexpr const char CB_DELEGATE_DEFS[] = -R"__c_cb( -typedef struct rpc_port_delegate_s { - rpc_port_parcelable_t parcelable; - int id; - int seq_id; - bool once; -} rpc_port_delegate_t; - -typedef rpc_port_delegate_t *rpc_port_delegate_h; - -static rpc_port_delegate_h rpc_port_delegate_create(int id, int seq_id, bool once); -)__c_cb"; - -constexpr const char CB_DELEGATE_BASE[] = -R"__c_cb( -static void __rpc_port_delegate_to(rpc_port_parcel_h parcel, void *user_data) -{ - rpc_port_delegate_h delegate = user_data; - rpc_port_unit_map_h map; - - map = rpc_port_unit_map_create(); - if (map == nullptr) { - set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); - return; - } - - rpc_port_unit_map_write_int(map, "id", delegate->id); - rpc_port_unit_map_write_int(map, "seq_id", delegate->seq_id); - rpc_port_unit_map_write_bool(map, "once", delegate->once); - rpc_port_parcel_write(parcel, &map->parcelable, map); - rpc_port_unit_map_destroy(map); - set_last_result(RPC_PORT_ERROR_NONE); -} - -static void __rpc_port_delegate_from(rpc_port_parcel_h parcel, void *user_data) -{ - rpc_port_delegate_h delegate = user_data; - rpc_port_unit_map_h map; - - map = rpc_port_unit_map_create(); - if (map == nullptr) { - set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); - return; - } - - rpc_port_parcel_read(parcel, &map->parcelable, map); - rpc_port_unit_map_read_int(map, "id", &delegate->id); - rpc_port_unit_map_read_int(map, "seq_id", &delegate->seq_id); - rpc_port_unit_map_read_bool(map, "once", &delegate->once); - rpc_port_unit_map_destroy(map); - set_last_result(RPC_PORT_ERROR_NONE); -} - -static void rpc_port_delegate_destroy(rpc_port_delegate_h handle) -{ - if (handle == nullptr) - return; - - free(handle); -} - -static rpc_port_delegate_h rpc_port_delegate_create(int id, int seq_id, bool once) -{ - rpc_port_delegate_h delegate; - - delegate = malloc(sizeof(rpc_port_delegate_t)); - if (delegate == nullptr) { - _E("malloc() is failed"); - return nullptr; - } - - delegate->parcelable.to = __rpc_port_delegate_to; - delegate->parcelable.from = __rpc_port_delegate_from; - delegate->id = id; - delegate->seq_id = seq_id; - delegate->once = once; - - return delegate; -} -)__c_cb"; - constexpr const char CB_UNIT_MAP_DEFS[] = R"__c_cb( typedef struct rpc_port_unit_s { @@ -339,7 +257,10 @@ static rpc_port_unit_map_h rpc_port_unit_map_create(void) return unit_map; } +)__c_cb"; +constexpr const char CB_UNIT_MAP_CLEAR_BASE[] = +R"__c_cb( static int rpc_port_unit_map_clear(rpc_port_unit_map_h map) { if (map == nullptr) { @@ -518,7 +439,7 @@ static int rpc_port_unit_map_read_delegate(rpc_port_unit_map_h unit_map, if (unit_map == nullptr || name == nullptr || value == nullptr) return RPC_PORT_ERROR_INVALID_PARAMETER; - delegate = rpc_port_delegate_create(0, 0, false); + delegate = rpc_port_delegate_create(); if (delegate == NULL) return RPC_PORT_ERROR_OUT_OF_MEMORY; diff --git a/idlc/gen/version2/c_group_body_generator_cb.hh b/idlc/gen/version2/c_group_body_generator_cb.hh index c9a837b..f931555 100644 --- a/idlc/gen/version2/c_group_body_generator_cb.hh +++ b/idlc/gen/version2/c_group_body_generator_cb.hh @@ -171,7 +171,7 @@ static void ___event_system_cb(const char *event_name, bundle *event_data, rpc_port_parcel_h header; int seq_num = -1; int cmd; - rpc_port_unit_map_h map; + rpc_port_unit_map_h map; rpc_port_parcel_get_header(p, &header); rpc_port_parcel_header_get_seq_num(header, &seq_num); @@ -196,7 +196,6 @@ static void ___event_system_cb(const char *event_name, bundle *event_data, } else { _W("Invalid protocol. cmd(%d)", cmd); } - rpc_port_unit_map_clear(map); rpc_port_unit_map_destroy(map); } diff --git a/idlc/gen/version2/c_proxy_body_generator.cc b/idlc/gen/version2/c_proxy_body_generator.cc index f9aaaa4..419f799 100644 --- a/idlc/gen/version2/c_proxy_body_generator.cc +++ b/idlc/gen/version2/c_proxy_body_generator.cc @@ -51,6 +51,14 @@ void CProxyBodyGenerator::OnInitGen(std::ofstream& stream) { void CProxyBodyGenerator::OnFiniGen(std::ofstream& stream) { } +void CProxyBodyGenerator::GenDelegateDefinition(std::ofstream& stream) { + stream << SmartIndent(CB_DELEGATE_DEFS); +} + +void CProxyBodyGenerator::GenDelegateBase(std::ofstream& stream) { + stream << SmartIndent(CB_DELEGATE_BASE); +} + void CProxyBodyGenerator::GenInterfaceDelegateCallback(std::ofstream& stream) { stream << SmartIndent(CB_INTERFACE_DELEGATE_CALLBACK); } @@ -488,7 +496,7 @@ void CProxyBodyGenerator::GenInterfaceDelegateEnumBase(std::ofstream& stream, unsigned int num = 1; std::string enums; for (const auto& decl : iface.GetDeclarations()) { - if (decl->GetMethodType() == Declaration::MethodType::DELEGATE) + if (decl->GetMethodType() != Declaration::MethodType::DELEGATE) continue; enums += GetHandlePrefix() + "_" + iface.GetID() + "_DELEGATE_" + diff --git a/idlc/gen/version2/c_proxy_body_generator.hh b/idlc/gen/version2/c_proxy_body_generator.hh index 4a205bd..ed4df29 100644 --- a/idlc/gen/version2/c_proxy_body_generator.hh +++ b/idlc/gen/version2/c_proxy_body_generator.hh @@ -77,6 +77,8 @@ class CProxyBodyGenerator : public CBodyGeneratorBase { const Declaration& decl, bool& has_free); void GenInterfaceDelegateEnumBase(std::ofstream& stream, const Interface& iface); + void GenDelegateDefinition(std::ofstream& stream); + void GenDelegateBase(std::ofstream& stream); private: std::shared_ptr options_; diff --git a/idlc/gen/version2/c_proxy_body_generator_cb.hh b/idlc/gen/version2/c_proxy_body_generator_cb.hh index 31359f7..4a7b35b 100644 --- a/idlc/gen/version2/c_proxy_body_generator_cb.hh +++ b/idlc/gen/version2/c_proxy_body_generator_cb.hh @@ -20,6 +20,85 @@ namespace tidl { namespace version2 { +constexpr const char CB_DELEGATE_DEFS[] = +R"__c_cb( +typedef struct rpc_port_delegate_s { + rpc_port_parcelable_t parcelable; + int id; + int seq_id; + bool once; +} rpc_port_delegate_t; + +typedef rpc_port_delegate_t *rpc_port_delegate_h; + +static rpc_port_delegate_h rpc_port_delegate_create(); +)__c_cb"; + +constexpr const char CB_DELEGATE_BASE[] = +R"__c_cb( +static void __rpc_port_delegate_to(rpc_port_parcel_h parcel, void *user_data) +{ + rpc_port_delegate_h delegate = user_data; + rpc_port_unit_map_h map; + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + rpc_port_unit_map_write_int(map, "id", delegate->id); + rpc_port_unit_map_write_int(map, "seq_id", delegate->seq_id); + rpc_port_unit_map_write_bool(map, "once", delegate->once); + rpc_port_parcel_write(parcel, &map->parcelable, map); + rpc_port_unit_map_destroy(map); + set_last_result(RPC_PORT_ERROR_NONE); +} + +static void __rpc_port_delegate_from(rpc_port_parcel_h parcel, void *user_data) +{ + rpc_port_delegate_h delegate = user_data; + rpc_port_unit_map_h map; + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + rpc_port_parcel_read(parcel, &map->parcelable, map); + rpc_port_unit_map_read_int(map, "id", &delegate->id); + rpc_port_unit_map_read_int(map, "seq_id", &delegate->seq_id); + rpc_port_unit_map_read_bool(map, "once", &delegate->once); + rpc_port_unit_map_destroy(map); + set_last_result(RPC_PORT_ERROR_NONE); +} + +static void rpc_port_delegate_destroy(rpc_port_delegate_h handle) +{ + if (handle == nullptr) + return; + + free(handle); +} + +static rpc_port_delegate_h rpc_port_delegate_create() +{ + rpc_port_delegate_h delegate; + + delegate = calloc(1, sizeof(rpc_port_delegate_t)); + if (delegate == nullptr) { + _E("malloc() is failed"); + return nullptr; + } + + delegate->parcelable.to = __rpc_port_delegate_to; + delegate->parcelable.from = __rpc_port_delegate_from; + + return delegate; +} +)__c_cb"; + constexpr const char CB_INTERFACE_DELEGATE_CALLBACK[] = R"__c_cb( typedef void (*rpc_port_proxy_delegate_cb)(GList **delegates, rpc_port_unit_map_h map, rpc_port_delegate_h delegate); @@ -183,7 +262,6 @@ int ___destroy(___h h) int ___clone(___h h, ___h *clone) { - ___h handle; rpc_port_unit_map_h map; int ret; @@ -198,14 +276,14 @@ int ___clone(___h h, < return RPC_PORT_ERROR_OUT_OF_MEMORY; } - ret = rpc_port_unit_map_write_(map, "clone", h); + ret = rpc_port_unit_map_write__(map, "clone", h); if (ret != RPC_PORT_ERROR_NONE) { _E("Failed to write . error(%d)", ret); rpc_port_unit_map_destroy(map); return ret; } - ret = rpc_port_unit_map_read_(map, "clone", clone); + ret = rpc_port_unit_map_read__(map, "clone", clone); rpc_port_unit_map_destroy(map); return ret; @@ -795,6 +873,7 @@ void __invoke_(__h h) { rpc_port_parcel_h parcel_; rpc_port_parcel_header_h header_; + rpc_port_unit_map_h map_; int seq_num_ = -1; int res_; @@ -994,7 +1073,6 @@ rpc_port_unit_map_write_(map_, "", ); */ constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_READ[] = R"__c_cb( - = nullptr; res_ = rpc_port_unit_map_read_(map_, "", &); if (res_ != RPC_PORT_ERROR_NONE) { _E("Failed to read . error(%d)", res); @@ -1009,7 +1087,6 @@ if (res_ != RPC_PORT_ERROR_NONE) { */ constexpr const char CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_READ[] = R"__c_cb( - = nullptr; res_ = rpc_port_unit_map_read_bundle(map_, "", &); if (res_ != RPC_PORT_ERROR_NONE) { _E("Failed to read bundle. error(%d)", res_); @@ -1024,7 +1101,6 @@ if (res_ != RPC_PORT_ERROR_NONE) { */ constexpr const char CB_INTERFACE_METHOD_STRING_UNIT_MAP_READ[] = R"__c_cb( - = nullptr; res_ = rpc_port_unit_map_read_string(map_, "", &); if (res_ != RPC_PORT_ERROR_NONE) { _E("Failed to read string. error(%d)", res_); diff --git a/idlc/gen/version2/c_stub_body_generator.cc b/idlc/gen/version2/c_stub_body_generator.cc new file mode 100644 index 0000000..4becb46 --- /dev/null +++ b/idlc/gen/version2/c_stub_body_generator.cc @@ -0,0 +1,704 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "idlc/gen/version2/c_stub_body_generator.hh" +#include "idlc/gen/version2/c_stub_body_generator_cb.hh" + +namespace tidl { +namespace version2 { + +CStubBodyGenerator::CStubBodyGenerator(std::shared_ptr doc, + std::shared_ptr options) + : CBodyGeneratorBase(doc), options_(options) { +} + +void CStubBodyGenerator::OnInitGen(std::ofstream& stream) { + GenVersion(stream); + GenGNUSourceDefinition(stream); + GenIncludeDefaultHeaders(stream); + GenIncludeHeader(stream); + GenLogTag(stream, std::string("RPC_PORT_STUB")); + GenLogDefinition(stream); + GenVersionDefinition(stream); + GenBaseDefinition(stream); + GenThreadEnableDefinition(stream); + GenInterfaceEnums(stream); + GenUnitMapDefinition(stream); + GenInterfaceMethodHandlerType(stream); + GenDelegateDefinition(stream); + GenStructureDefinition(stream); + GenInterfaceDefs(stream); + GenPrivateSharingListSet(stream); + GenUnitMapBase(stream); + GenDelegateBase(stream); + GenStructure(stream); + GenInterfaces(stream); +} + +void CStubBodyGenerator::OnFiniGen(std::ofstream& stream) { +} + +void CStubBodyGenerator::GenDelegateDefinition(std::ofstream& stream) { + stream << SmartIndent(CB_DELEGATE_DEFS); +} + +void CStubBodyGenerator::GenDelegateBase(std::ofstream& stream) { + stream << SmartIndent(CB_DELEGATE_BASE); +} + +// @see #CB_THREAD_ENABLE_DEF +void CStubBodyGenerator::GenThreadEnableDefinition(std::ofstream& stream) { + if (!options_->IsThreadEnabled()) + return; + + stream << std::string(CB_THREAD_ENABLE_DEF); +} + +// @see #CB_INTERFACE_METHOD_HANDLER_TYPE +void CStubBodyGenerator::GenInterfaceMethodHandlerType(std::ofstream& stream) { + stream << SmartIndent(CB_INTERFACE_METHOD_HANDLER_TYPE); +} + +void CStubBodyGenerator::GenInterfaceEnums(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + GenInterfaceEnum(stream, iface); + } +} + +void CStubBodyGenerator::GenInterfaceEnum(std::ofstream& stream, + const Interface& iface) { + GenInterfaceMethodEnumBase(stream, iface); + GenInterfaceDelegateEnumBase(stream, iface); +} + +// @see #CB_INTERFACE_METHOD_ENUM +std::string CStubBodyGenerator::GenMethodEnums(const Interface& iface) { + std::string method_enum(ReplaceAll(CB_INTERFACE_METHOD_ENUM, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", "RESULT_" } + })); + + std::string method_enums = RemoveLine(method_enum); + + method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", "CALLBACK_" } + }); + + method_enums += RemoveLine(method_enum); + + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + method_enum = ReplaceAll(CB_INTERFACE_METHOD_ENUM, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", d->GetID() } + }); + + method_enums += RemoveLine(method_enum); + } + std::transform(method_enums.begin(), method_enums.end(), method_enums.begin(), + ::toupper); + + return method_enums; +} + +// @see #CB_INTERFACE_METHOD_ENUM_BASE +void CStubBodyGenerator::GenInterfaceMethodEnumBase(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", GenMethodEnums(iface) } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_DELEGATE_ENUM +std::string CStubBodyGenerator::GenDelegateEnums(const Interface& iface) { + unsigned int num = 1; + std::string method_enums; + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + std::string method_enum(ReplaceAll(CB_INTERFACE_DELEGATE_ENUM, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", d->GetID() }, + { "", std::to_string(num++) } + })); + + method_enums += RemoveLine(method_enum); + } + std::transform(method_enums.begin(), method_enums.end(), method_enums.begin(), + ::toupper); + + return method_enums; +} + +// @see #CB_INTERFACE_DELEGATE_ENUM_BASE +void CStubBodyGenerator::GenInterfaceDelegateEnumBase(std::ofstream& stream, + const Interface& iface) { + std::string delegate_enums = GenDelegateEnums(iface); + if (delegate_enums.empty()) + return; + + std::string code(ReplaceAll(CB_INTERFACE_DELEGATE_ENUM_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", delegate_enums } + })); + + stream << SmartIndent(code); +} + +void CStubBodyGenerator::GenInterfaceDefs(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + GenInterfaceDef(stream, iface); + } +} + +void CStubBodyGenerator::GenInterfaceDef(std::ofstream& stream, + const Interface& iface) { + bool has_delegate = false; + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateDef(stream, iface, *d); + has_delegate = true; + } + + if (has_delegate) + GenInterfaceCallbackPortCheckDef(stream, iface); + + GenInterfaceContextDef(stream, iface); + GenInterfaceBaseDef(stream, iface); +} + +// @see #CB_INTERFACE_DELEGATE_DEF +void CStubBodyGenerator::GenInterfaceDelegateDef(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string code(ReplaceAll(CB_INTERFACE_DELEGATE_DEF, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_CALLBACK_PORT_CHECK_DEF +void CStubBodyGenerator::GenInterfaceCallbackPortCheckDef(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CALLBACK_PORT_CHECK_DEF, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_CONTEXT_DEF +void CStubBodyGenerator::GenInterfaceContextDef(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CONTEXT_DEF, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_BASE_DEF +void CStubBodyGenerator::GenInterfaceBaseDef(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_BASE_DEF, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +void CStubBodyGenerator::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + + const Interface &iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CStubBodyGenerator::GenInterface(std::ofstream& stream, const Interface& iface) { + bool has_delegate = false; + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateBase(stream, iface, *d); + has_delegate = true; + } + + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceMethodHandlerBase(stream, iface, *d); + } + + GenInterfaceMethodTable(stream, iface); + GenInterfaceContextBase(stream, iface); + + if (has_delegate) + GenInterfaceCallbackPortCheck(stream, iface); + + GenInterfaceBase(stream, iface); +} + +// @see #CB_INTERFACE_CONTEXT_BASE +void CStubBodyGenerator::GenInterfaceContextBase(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CONTEXT_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +std::string CStubBodyGenerator::GenDelegateParams(const Interface& iface, + const Declaration& decl) { + std::string params; + for (const auto& p : decl.GetParameters()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, iface) + + p->GetID(); + } + + return params; +} + +std::string CStubBodyGenerator::GenDelegateParamsCheck(const Interface& iface, + const Declaration& decl) { + std::string params_check; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(iface, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array" || + type.ToString() == "bundle" || + type.ToString() == "string" || + type.ToString() == "file") + params_check += " || " + p->GetID() + " == nullptr"; + } + + return params_check; +} + +// @see #CB_INTERFACE_DELEGATE_BASE +void CStubBodyGenerator::GenInterfaceDelegateBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string enum_value = GetHandlePrefix() + "_" + iface.GetID() + + "_DELEGATE_" + decl.GetID(); + std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(), + ::toupper); + + std::string prefix = GetHandlePrefix(); + std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper); + + std::string name = iface.GetID(); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + + std::string code(ReplaceAll(CB_INTERFACE_DELEGATE_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenDelegateParams(iface, decl) }, + { "", GenDelegateParamsCheck(iface, decl) }, + { "", enum_value }, + { "", GenDelegateUnitMapWrite(iface, decl) }, + { "", prefix }, + { "", name } + })); + + stream << SmartIndent(code); +} + +std::string CStubBodyGenerator::GenMethodHandlerArgsDecl(const Interface& iface, + const Declaration& decl) { + std::string args_decl; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + args_decl += GetArgTypeString(type, iface) + p->GetID() + " = " + + GetErrorValue(type) + ";" + NLine(1); + } + + if (decl.GetMethodType() == Declaration::MethodType::SYNC) { + args_decl += "rpc_port_parcel_h parcel_;" + NLine(1); + args_decl += "rpc_port_unit_map_h map_;" + NLine(1); + args_decl += GetArgTypeString(decl.GetType(), iface) + "res_ = " + + GetErrorValue(decl.GetType()) + ";" + NLine(1); + } + + return args_decl; +} + +// @see #CB_INTERFACE_METHOD_DELEGATE_UNIT_MAP_READ +// @see #CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_READ +// @see #CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_READ +// @see #CB_INTERFACE_METHOD_STRING_UNIT_MAP_READ +// @see #CB_INTERFACE_METHOD_BASE_UNIT_MAP_READ +std::string CStubBodyGenerator::GenMethodUnitMapRead(const Interface& iface, + const Declaration& decl) { + std::string code; + for (const auto& p : decl.GetParameters()) { + std::string parcel_read_code; + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) + continue; + + auto& type = param_type.GetBaseType(); + if (IsDelegateType(iface, type)){ + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_DELEGATE_UNIT_MAP_READ) + .Change("", GetHandlePrefix()) + .Change("", GetFullNameFromType(type, iface)) + .Change("", std::string("delegate")) + .Change("", p->GetID()); + + } else if (type.IsUserDefinedType() || type.GetMetaType() != nullptr) { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_READ) + .Change("", GetFullNameFromType(type, iface)) + .Change("", p->GetID()) + .Change("", p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_READ) + .Change("", p->GetID()) + .Change("", p->GetID()); + } else if (type.ToString() == "string" || type.ToString() == "file") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_UNIT_MAP_READ) + .Change("", p->GetID()) + .Change("", p->GetID()); + } else { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_UNIT_MAP_READ) + .Change("", GetFullNameFromType(type, iface)) + .Change("", p->GetID()) + .Change("", p->GetID()); + } + + code += parcel_read_code; + } + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_INVOKE +std::string CStubBodyGenerator::GenMethodHandlerCallbackInvoke( + const Declaration& decl) { + std::string code(ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_INVOKE, + "", decl.GetID())); + + if (decl.GetMethodType() == Declaration::MethodType::SYNC) + code = ReplaceAll(code, "", "res_ = "); + else + code = ReplaceAll(code, "", ""); + + std::string args; + for (const auto& p : decl.GetParameters()) { + args += ", "; + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) + args += "&"; + + args += p->GetID(); + } + code = ReplaceAll(code, "", args); + + return RemoveLine(code); +} + +std::string CStubBodyGenerator::GenDelegateUnitMapWrite( + const Interface& iface, const Declaration& decl) { + std::string parcel_write_code; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + parcel_write_code += GenMethodUnitMapWriteBase( + iface, param_type.GetBaseType(), p->GetID(), p->GetID()); + } + return RemoveLine(parcel_write_code); +} + +// @see #CB_INTERFACE_METHOD_DELEGATE_UNIT_MAP_WRITE +// @see #CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_WRITE +// @see #CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_WRITE +// @see #CB_INTERFACE_METHOD_STRING_UNIT_MAP_WRITE +// @see #CB_INTERFACE_METHOD_BASE_UNIT_MAP_WRITE +std::string CStubBodyGenerator::GenMethodUnitMapWriteBase( + const Interface& iface, const BaseType& type, + const std::string& arg_name, const std::string& arg) { + std::string parcel_write_code; + + if (IsDelegateType(iface, type)) { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_DELEGATE_UNIT_MAP_WRITE) + .Change("", std::string("delegate")) + .Change("", arg); + } else if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_WRITE) + .Change("", GetFullNameFromType(type, iface)) + .Change("", arg_name) + .Change("", arg); + parcel_write_code += GetPrivateSharingString(type, iface, "port", arg); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_WRITE) + .Change("", arg_name) + .Change("", arg); + } else if (type.ToString() == "string") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_UNIT_MAP_WRITE) + .Change("", arg_name) + .Change("", arg); + } else if (type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_UNIT_MAP_WRITE) + .Change("", arg_name) + .Change("", arg); + parcel_write_code += GetPrivateSharingString(type, iface, "port", arg_name); + } else { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_UNIT_MAP_WRITE) + .Change("", GetFullNameFromType(type, iface)) + .Change("", arg_name) + .Change("", arg); + } + + return parcel_write_code; +} +// @see #CB_INTERFACE_METHOD_PARCEL_WRITE_PRE +// @see #CB_INTERFACE_METHOD_PARCEL_WRITE_POST +std::string CStubBodyGenerator::GenMethodUnitMapWrite(const Interface& iface, + const Declaration& decl) { + std::string code; + if (decl.GetMethodType() != Declaration::MethodType::SYNC) + return code; + + std::string prefix = GetHandlePrefix(); + std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper); + code = ReplaceAll(CB_INTERFACE_METHOD_PARCEL_WRITE_PRE, "", + prefix); + + std::string name = iface.GetID(); + std::transform(name.begin(), name.end(), name.begin(), ::toupper); + code = ReplaceAll(code, "", name); + + std::string parcel_write_code; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() == ParameterType::Direction::IN) + continue; + code += GenMethodUnitMapWriteBase( + iface, param_type.GetBaseType(), p->GetID(), p->GetID()); + } + + code += GenMethodUnitMapWriteBase(iface, decl.GetType(), "[RESULT]", "res_"); + + 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 CStubBodyGenerator::GenMethodHandlerArgsFree(const Interface& iface, + const Declaration& decl) { + std::string free_code; + std::string code; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (IsDelegateType(iface, type) || + type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_USER_DEFINED_FREE, + "", GetHandlePrefix()); + free_code = ReplaceAll(free_code, "", + GetFullNameFromType(type, iface)); + 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(iface, 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, iface)); + 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 CStubBodyGenerator::GenInterfaceMethodHandlerBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string code(ReplaceAll(CB_INTERFACE_METHOD_HANDLER_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenMethodHandlerArgsDecl(iface, decl) }, + { "", + GenMethodUnitMapRead(iface, decl) }, + { "", + GenMethodHandlerCallbackInvoke(decl) }, + { "", + GenMethodUnitMapWrite(iface, decl) }, + { "", GenMethodHandlerArgsFree(iface, decl) } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_METHOD_HANDLER +std::string CStubBodyGenerator::GenMethodHandlers(const Interface& iface) { + std::string code; + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + std::string enum_value = GetHandlePrefix() + "_" + iface.GetID() + + "_METHOD_" + d->GetID(); + std::transform(enum_value.begin(), enum_value.end(), enum_value.begin(), + ::toupper); + std::string method_handler(ReplaceAll(CB_INTERFACE_METHOD_HANDLER, { + { "", enum_value }, + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", d->GetID() } + })); + + code += RemoveLine(method_handler); + } + + return code; +} + +// @see #CB_INTERFACE_METHOD_TABLE +void CStubBodyGenerator::GenInterfaceMethodTable(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_METHOD_TABLE, { + { "", iface.GetID() }, + { "", GenMethodHandlers(iface) } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_CALLBACK_PORT_CHECK +void CStubBodyGenerator::GenInterfaceCallbackPortCheck(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CALLBACK_PORT_CHECK, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_PRIVILEGE_ADD +// @see #CB_INTERFACE_TRUSTED_SET +std::string CStubBodyGenerator::GenAccessControlSet(const Interface& iface) { + std::string code; + for (const auto& attr : iface.GetAttributes()) { + if (attr->GetKey() == "privilege") { + std::string privilege_add(ReplaceAll(CB_INTERFACE_PRIVILEGE_ADD, { + { "", iface.GetID() }, + { "", attr->GetValue() } + })); + + code += privilege_add; + } else if (attr->GetKey() == "trusted" && attr->GetValue() == "true") { + std::string trusted_set(ReplaceAll(CB_INTERFACE_TRUSTED_SET, + "", iface.GetID())); + + code += trusted_set; + } + } + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_BASE +void CStubBodyGenerator::GenInterfaceBase(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", GenAccessControlSet(iface) } + })); + + stream << SmartIndent(code); +} + +} // namespace version2 +} // namespace tidl diff --git a/idlc/gen/version2/c_stub_body_generator.hh b/idlc/gen/version2/c_stub_body_generator.hh new file mode 100644 index 0000000..639f476 --- /dev/null +++ b/idlc/gen/version2/c_stub_body_generator.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_C_GEN_C_STUB_BODY_GENERATOR_HH_ +#define IDLC_C_GEN_C_STUB_BODY_GENERATOR_HH_ + +#include +#include + +#include "idlc/gen/version2/c_body_generator_base.hh" +#include "idlc/options.h" + +namespace tidl { +namespace version2 { + +class CStubBodyGenerator : public CBodyGeneratorBase { + public: + explicit CStubBodyGenerator(std::shared_ptr doc, + std::shared_ptr options); + virtual ~CStubBodyGenerator() = default; + + void OnInitGen(std::ofstream& stream) override; + 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& iface); + void GenInterfaceMethodEnumBase(std::ofstream& stream, + const Interface& iface); + void GenInterfaceDelegateEnumBase(std::ofstream& stream, + const Interface& iface); + + void GenInterfaceDefs(std::ofstream& stream); + void GenInterfaceDef(std::ofstream& stream, const Interface& iface); + void GenInterfaceContextDef(std::ofstream& stream, const Interface& iface); + void GenInterfaceDelegateDef(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + void GenInterfaceCallbackPortCheckDef(std::ofstream& stream, + const Interface& iface); + void GenInterfaceBaseDef(std::ofstream& stream, const Interface& iface); + + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenInterfaceContextBase(std::ofstream& stream, const Interface& iface); + void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + void GenInterfaceMethodHandlerBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl); + void GenInterfaceMethodTable(std::ofstream& stream, const Interface& iface); + void GenInterfaceCallbackPortCheck(std::ofstream& stream, + const Interface& iface); + void GenInterfaceBase(std::ofstream& stream, const Interface& iface); + + std::string GenMethodEnums(const Interface& iface); + std::string GenDelegateEnums(const Interface& iface); + + std::string GenDelegateParams(const Interface& iface, + const Declaration& decl); + std::string GenDelegateParamsCheck(const Interface& iface, + const Declaration& decl); + std::string GenMethodHandlerArgsDecl(const Interface& iface, + const Declaration& decl); + std::string GenMethodUnitMapRead(const Interface& iface, + const Declaration& decl); + std::string GenMethodHandlerCallbackInvoke(const Declaration& decl); + std::string GenMethodUnitMapWriteBase( + const Interface& iface, const BaseType& type, + const std::string& arg_name, const std::string& arg); + std::string GenMethodUnitMapWrite(const Interface& iface, + const Declaration& decl); + std::string GenDelegateUnitMapWrite( + const Interface& iface, const Declaration& decl); + std::string GenMethodHandlerArgsFree(const Interface& iface, + const Declaration& decl); + std::string GenMethodHandlers(const Interface& iface); + std::string GenAccessControlSet(const Interface& iface); + void GenDelegateDefinition(std::ofstream& stream); + void GenDelegateBase(std::ofstream& stream); + + private: + std::shared_ptr options_; +}; + +} // namespace version2 +} // namespace tidl + +#endif // IDLC_C_GEN_C_STUB_BODY_GENERATOR_HH_ diff --git a/idlc/gen/version2/c_stub_body_generator_cb.hh b/idlc/gen/version2/c_stub_body_generator_cb.hh new file mode 100644 index 0000000..64a93da --- /dev/null +++ b/idlc/gen/version2/c_stub_body_generator_cb.hh @@ -0,0 +1,1408 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_C_GEN_C_STUB_BODY_GENERATOR_CB_H_ +#define IDLC_C_GEN_C_STUB_BODY_GENERATOR_CB_H_ + +constexpr const char CB_DELEGATE_DEFS[] = +R"__c_cb( +typedef struct rpc_port_delegate_s { + rpc_port_parcelable_t parcelable; + rpc_port_h port; + int id; + int seq_id; + bool once; + bool valid; +} rpc_port_delegate_t; + +typedef rpc_port_delegate_t *rpc_port_delegate_h; + +static rpc_port_delegate_h rpc_port_delegate_create(); +)__c_cb"; + +constexpr const char CB_DELEGATE_BASE[] = +R"__c_cb( +static void __rpc_port_delegate_to(rpc_port_parcel_h parcel, void *user_data) +{ + rpc_port_delegate_h delegate = user_data; + rpc_port_unit_map_h map; + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + rpc_port_unit_map_write_int(map, "id", delegate->id); + rpc_port_unit_map_write_int(map, "seq_id", delegate->seq_id); + rpc_port_unit_map_write_bool(map, "once", delegate->once); + rpc_port_unit_map_write_bool(map, "valid", delegate->valid); + rpc_port_parcel_write(parcel, &map->parcelable, map); + rpc_port_unit_map_destroy(map); + set_last_result(RPC_PORT_ERROR_NONE); +} + +static void __rpc_port_delegate_from(rpc_port_parcel_h parcel, void *user_data) +{ + rpc_port_delegate_h delegate = user_data; + rpc_port_unit_map_h map; + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + rpc_port_parcel_read(parcel, &map->parcelable, map); + rpc_port_unit_map_read_int(map, "id", &delegate->id); + rpc_port_unit_map_read_int(map, "seq_id", &delegate->seq_id); + rpc_port_unit_map_read_bool(map, "once", &delegate->once); + rpc_port_unit_map_read_bool(map, "valid", &delegate->valid); + rpc_port_unit_map_destroy(map); + set_last_result(RPC_PORT_ERROR_NONE); +} + +static rpc_port_delegate_h rpc_port_delegate_create() +{ + rpc_port_delegate_h delegate; + + delegate = calloc(1, sizeof(rpc_port_delegate_t)); + if (delegate == nullptr) { + _E("malloc() is failed"); + return nullptr; + } + + delegate->parcelable.to = __rpc_port_delegate_to; + delegate->parcelable.from = __rpc_port_delegate_from; + + return delegate; +} +)__c_cb"; + +constexpr const char CB_THREAD_ENABLE_DEF[] = +R"__c_cb( +#define TIDL_THREAD_ENABLE 1 +)__c_cb"; + +constexpr const char CB_INTERFACE_METHOD_HANDLER_TYPE[] = +R"__c_cb( +typedef int (*rpc_port_stub_method_handler)(rpc_port_h port, rpc_port_parcel_h parcel, rpc_port_unit_map_h map, void *data); +)__c_cb"; + +/** + * 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"; + +/** + * 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"; + +/** + * 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( +typedef enum { + +} __delegate_e; +)__c_cb"; + +/** + * 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( +__DELEGATE_ = , +)__c_cb"; + +/** + * 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"; + +/** + * 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; +)__c_cb"; + +/** + * + */ +constexpr const char CB_INTERFACE_CALLBACK_PORT_CHECK_DEF[] = +R"__c_cb( +static bool ____exist_callback_port(rpc_port_h callback_port); +)__c_cb"; + +/** + * 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"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_BASE[] = +R"__c_cb( +static int ____context_handle_request(__context_h h, rpc_port_parcel_h parcel) +{ + int ret = RPC_PORT_ERROR_NONE; + int cmd = -1; + rpc_port_unit_map_h map; + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + _E("Failed to create unit map"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + rpc_port_parcel_read(parcel, &map->parcelable, map); + + rpc_port_unit_map_read_int(map, "[METHOD]", &cmd); + + if (cmd > 1 && cmd < ARRAY_SIZE(___method_table)) { + if (___method_table[cmd]) + ret = ___method_table[cmd](h->port, parcel, map, h); + } else { + _W("Invalid protocol. cmd(%d)", cmd); + ret = RPC_PORT_ERROR_INVALID_PARAMETER; + } + rpc_port_unit_map_destroy(map); + + return ret; +} + +#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); + + return 0; +} + +static rpc_port_parcel_h ____context_wait_and_pop(__context_h h) +{ + rpc_port_parcel_h parcel; + + g_mutex_lock(&h->mutex); + while (g_queue_is_empty(h->queue) && !h->done) + g_cond_wait(&h->cond, &h->mutex); + + parcel = g_queue_pop_head(h->queue); + g_mutex_unlock(&h->mutex); + + return parcel; +} + +static gpointer ____context_thread_cb(gpointer user_data) +{ + __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"); + + return nullptr; +} +#endif /* TIDL_THREAD_ENABLE */ + +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); + } + + g_queue_free(h->queue); + } +#endif /* TIDL_THREAD_ENABLE */ + + if (h->instance) + free(h->instance); + + if (h->sender) + free(h->sender); + + free(h); +} + +static __context_h ____context_create(const char *sender, const char *instance, rpc_port_h callback_port) +{ + __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; +} + +int __context_set_tag(__context_h context, void *tag) +{ + if (context == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + context->tag = tag; + + return RPC_PORT_ERROR_NONE; +} + +int __context_get_tag(__context_h context, void **tag) +{ + if (context == nullptr || tag == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *tag = context->tag; + + return RPC_PORT_ERROR_NONE; +} + +int __context_get_sender(__context_h context, char **sender) +{ + char *value; + + if (context == nullptr || sender == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + value = strdup(context->sender); + if (value == nullptr) { + _E("Failed to duplicate sender"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + *sender = value; + + return RPC_PORT_ERROR_NONE; +} + +int __context_get_instance(__context_h context, char **instance) +{ + char *value; + + if (context == nullptr || instance == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + value = strdup(context->instance); + if (value == nullptr) { + _E("Failed to duplicate instance"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + *instance = value; + + return RPC_PORT_ERROR_NONE; +} + +int __context_disconnect(__context_h context) +{ + int ret; + + if (context == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + g_rec_mutex_lock(&__.mutex); + + ret = rpc_port_disconnect(context->callback_port); + if (ret != RPC_PORT_ERROR_NONE) + _E("Failed to disconnect. error(%d)", ret); + + g_rec_mutex_unlock(&__.mutex); + + return ret; +} + +static __context_h ____find_context(const char *instance) +{ + __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; + } + + iter = g_list_next(iter); + } + g_rec_mutex_unlock(&__.mutex); + + return nullptr; +} + +static void ____add_context(__context_h context) +{ + 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); +} +)__c_cb"; + +/** + * 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. + * The uppercase prefix of the interface. + * The uppercase name of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_BASE[] = +R"__c_cb( +static void _____to(rpc_port_parcel_h parcel, void *user_data) +{ + ___h h = user_data; + rpc_port_unit_map_h map; + + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + _E("Failed to create unit map"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + rpc_port_unit_map_write_int(map, "id", h->id); + rpc_port_unit_map_write_int(map, "seq_id", h->seq_id); + rpc_port_unit_map_write_bool(map, "once", h->once); + + rpc_port_parcel_write(parcel, &map->parcelable, map); + rpc_port_unit_map_destroy(map); + + _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); + set_last_result(RPC_PORT_ERROR_NONE); +} + +static void _____from(rpc_port_parcel_h parcel, void *user_data) +{ + ___h h = user_data; + rpc_port_unit_map_h map; + int ret; + + if (parcel == nullptr || h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + _E("Failed to create unit map"); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + rpc_port_parcel_read(parcel, &map->parcelable, map); + + ret = rpc_port_unit_map_read_int(map, "id", &h->id); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read id. error(%d)", ret); + rpc_port_unit_map_destroy(map); + set_last_result(ret); + return; + } + + ret = rpc_port_unit_map_read_int(map, "seq_id", &h->seq_id); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to read seq_id. error(%d)", ret); + rpc_port_unit_map_destroy(map); + set_last_result(ret); + return; + } + + ret = rpc_port_unit_map_read_bool(map, "once", &h->once); + rpc_port_unit_map_destroy(map); + + _I("id(%d), seq_id(%d), once(%s)", h->id, h->seq_id, h->once ? "true" : "false"); + set_last_result(ret); +} + +int ___create(___h *h) +{ + ___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; +} + +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"); + + free(h); + + return RPC_PORT_ERROR_NONE; +} + +int ___clone(___h h, ___h *clone) +{ + rpc_port_unit_map_h map; + int ret; + + if (h == nullptr || clone == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + map = rpc_port_unit_map_create(); + if (map == nullptr) { + _E("Failed to create unit map"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + ret = rpc_port_unit_map_write__(map, "clone", h); + if (ret != RPC_PORT_ERROR_NONE) { + _E("Failed to write . error(%d)", ret); + rpc_port_unit_map_destroy(map); + return ret; + } + + ret = rpc_port_unit_map_read__(map, "clone", clone); + rpc_port_unit_map_destroy(map); + + (*clone)->port = h->port; + + return ret; +} + +int ___get_id(___h h, int *id) +{ + if (h == nullptr || id == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *id = h->id; + + return RPC_PORT_ERROR_NONE; +} + +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; +} + +int ___is_once(___h h, bool *once) +{ + if (h == nullptr || once == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *once = h->once; + + return RPC_PORT_ERROR_NONE; +} + +int ___get_tag(___h h, char **tag) +{ + char *value; + char buf[128]; + + if (h == nullptr || tag == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + 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; + } + + *tag = value; + + return RPC_PORT_ERROR_NONE; +} + +int ___set_port(___h h, rpc_port_h port) +{ + if (h == nullptr || port == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + h->port = port; + + return RPC_PORT_ERROR_NONE; +} + +int ___invoke(___h h) +{ + rpc_port_parcel_h parcel_; + int ret_; + rpc_port_unit_map_h map_; + + if (h == nullptr || h->port == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + if (!____exist_callback_port(h->port)) { + _E("Not connected"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + if (h->once && !h->valid) { + _E("The delegate handle is already used"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + ret_ = rpc_port_parcel_create(&parcel_); + if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", ret_); + return ret_; + } + + map_ = rpc_port_unit_map_create(); + if (map_ == nullptr) { + _E("Failed to create unit map"); + rpc_port_parcel_destroy(parcel_); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return ret_; + } + + rpc_port_unit_map_write_int(map_, "[METHOD]", __METHOD_CALLBACK_); + + rpc_port_unit_map_write_delegate(map_, "delegate", (rpc_port_delegate_h)h); + + + rpc_port_parcel_write(parcel_, &map_->parcelable, map_); + + rpc_port_unit_map_destroy(map_); + ret_ = rpc_port_parcel_send(parcel_, h->port); + rpc_port_parcel_destroy(parcel_); + h->valid = false; + + return ret_; +} +)__c_cb"; + + +/* + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_DELEGATE_UNIT_MAP_WRITE[] = +R"__c_cb( +rpc_port_unit_map_write_delegate(map_, "", (rpc_port_delegate_h)); +)__c_cb"; + + +/** + * The type name of the argument. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_WRITE[] = +R"__c_cb( +rpc_port_unit_map_write_(map_, "", ); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_WRITE[] = +R"__c_cb( +rpc_port_unit_map_write_bundle(map_, "", ); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_UNIT_MAP_WRITE[] = +R"__c_cb( +rpc_port_unit_map_write_string(map_, "", ); +)__c_cb"; + +/** + * The type name of the argument. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_UNIT_MAP_WRITE[] = +R"__c_cb( +rpc_port_unit_map_write_(map_, "", ); +)__c_cb"; + +/** + * The type name of the argument. + * The argument name. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_UNIT_MAP_READ[] = +R"__c_cb( +ret_ = rpc_port_unit_map_read_(map, "", &); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read . error(%d)", ret_); + goto out; +} +)__c_cb"; + +/** + * The argument name. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_UNIT_MAP_READ[] = +R"__c_cb( +ret_ = rpc_port_unit_map_read_bundle(map, "", &); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read bundle. error(%d)", ret_); + goto out; +} +)__c_cb"; + +/** + * The argument name. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_UNIT_MAP_READ[] = +R"__c_cb( +ret_ = rpc_port_unit_map_read_string(map, "", &); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read string. error(%d)", ret_); + goto out; +} +)__c_cb"; + +/* + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_DELEGATE_UNIT_MAP_READ[] = +R"__c_cb( +ret_ = rpc_port_unit_map_read_delegate(map, "", (rpc_port_delegate_h *)&); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read delegate. error(%d)", ret_); + goto out; +} +__set_port(, callback_port_); + +)__c_cb"; + + +/** + * The type name of the argument. + * The argument name. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_UNIT_MAP_READ[] = +R"__c_cb( +ret_ = rpc_port_unit_map_read_(map, "", &); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to read . error(%d)", ret_); + goto out; +} +)__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, rpc_port_unit_map_h map, void *user_data) +{ + __context_h context_ = user_data; + rpc_port_parcel_header_h header_; + int seq_num_ = -1; + rpc_port_h callback_port_; + int ret_; + + + + 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; + } + + rpc_port_parcel_get_header(parcel, &header_); + rpc_port_parcel_header_get_seq_num(header_, &seq_num_); + + + + + +out: + + + return ret_; +} +)__c_cb"; + +/** + * The argument. + * The prefix of the interface. + * The name of the interface + */ +constexpr const char CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ[] = +R"__c_cb( +ret_ = __create(&); +if (ret_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create handle. error(%d)", ret_); + goto out; +} + +__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"; + +/** + * 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; +} + +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"; + +/** + * 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"; + +/** + * The name of the value. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_string(parcel, &); +if ( == nullptr) { + _E("Failed to read data"); + ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + goto out; +} +)__c_cb"; + +/** + * The type of the parcel. + * The name of the value. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_(parcel, &); +)__c_cb"; + +/** + * 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 prefix of the interface. + * 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_get_header(parcel_, &header_); +rpc_port_parcel_header_set_tag(header_, TIDL_VERSION); +rpc_port_parcel_header_set_seq_num(header_, seq_num_); + +map_ = rpc_port_unit_map_create(); +if (map_ == nullptr) { + _E("Failed to create unit map"); + rpc_port_parcel_destroy(parcel_); + ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + goto out; +} + +rpc_port_unit_map_write_int(map_, "[METHOD]", __METHOD_RESULT_); +)__c_cb"; + +constexpr const char CB_INTERFACE_METHOD_PARCEL_WRITE_POST[] = +R"__c_cb( + +rpc_port_parcel_write(parcel_, &map_->parcelable, map_); +rpc_port_unit_map_destroy(map_); + +ret_ = rpc_port_parcel_send(parcel_, port); +rpc_port_parcel_destroy(parcel_); + +)__c_cb"; + +/** + * The argument. + * The prefix of the structure. + * The name of the structure. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_FREE[] = +R"__c_cb( +if () + __destroy(); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_FREE[] = +R"__c_cb( +if () + bundle_free(); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_FREE[] = +R"__c_cb( +if () + free(); +)__c_cb"; + +/** + * The name of the interface. + * The declarations of method handlers. + */ +constexpr const char CB_INTERFACE_METHOD_TABLE[] = +R"__c_cb( +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 ____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); +} + +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); +} + +static void ____connected_event_cb(const char *sender, const char *instance, void *user_data) +{ + __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; + + + _W("sender(%s), instance(%s)", sender, instance); + context = ____find_context(instance); + if (context == nullptr) + return; + + ____remove_callback_port(context->callback_port); + context->callback.terminate(context, context->user_data); + ____remove_context(context); + ____context_destroy(context); +} + +static int ____received_event_cb(const char *sender, const char *instance, rpc_port_h port, void *user_data) +{ + __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; +} + +static int ____set_access_control(void) +{ + int ret = RPC_PORT_ERROR_NONE; + + + + return ret; +} + +int __register(__callback_s *callback, void *user_data) +{ + 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); + g_rec_mutex_clear(&__.mutex); + 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; +} + +int __unregister(void) +{ + if (__.stub == nullptr) + return RPC_PORT_ERROR_NONE; + + g_rec_mutex_lock(&__.mutex); + g_rec_mutex_unlock(&__.mutex); + g_rec_mutex_clear(&__.mutex); + + 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; +} + +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; +} + +int __get_client_number(unsigned int *client_number) +{ + 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"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CALLBACK_PORT_CHECK[] = +R"__c_cb( +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; + } + + iter = g_list_next(iter); + } + g_rec_mutex_unlock(&__.mutex); + + return false; +} +)__c_cb"; + +/** + * 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"; + +/** + * 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"; + +#endif // IDLC_C_GEN_C_STUB_BODY_GENERATOR_CB_H_ diff --git a/idlc/gen/version2/c_stub_header_generator.cc b/idlc/gen/version2/c_stub_header_generator.cc new file mode 100644 index 0000000..20b451f --- /dev/null +++ b/idlc/gen/version2/c_stub_header_generator.cc @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "idlc/gen/version2/c_stub_header_generator.hh" + +namespace { +#include "idlc/gen/version2/c_stub_header_generator_cb.hh" +} + +namespace tidl { +namespace version2 { + +CStubHeaderGenerator::CStubHeaderGenerator(std::shared_ptr doc) + : CHeaderGeneratorBase(doc) {} + +void CStubHeaderGenerator::OnInitGen(std::ofstream& stream) { + GenVersion(stream); + GenPragmaOnce(stream); + GenIncludeDefaultHeaders(stream, false); + GenExplicitLinkageOpen(stream); + GenStructureHandles(stream); + GenInterfaceHandles(stream); + GenStructures(stream); + GenInterfaceCallbacks(stream); + GenInterfaces(stream); +} + +void CStubHeaderGenerator::OnFiniGen(std::ofstream& stream) { + GenExplicitLinkageClose(stream); +} + +void CStubHeaderGenerator::GenInterfaceHandles(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + GenInterfaceContextHandle(stream, iface); + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateHandle(stream, iface, *d); + } + } +} + +// @see #CB_INTERFACE_CONTEXT_HANDLE +void CStubHeaderGenerator::GenInterfaceContextHandle(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CONTEXT_HANDLE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_DELEGATE_HANDLE +void CStubHeaderGenerator::GenInterfaceDelegateHandle(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string code(ReplaceAll(CB_INTERFACE_DELEGATE_HANDLE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() } + })); + + stream << SmartIndent(code); +} + +void CStubHeaderGenerator::GenInterfaceCallbacks(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + GenInterfaceCallbackBase(stream, iface); + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceMethodCallbackBase(stream, iface, *d); + } + } +} + +// @see #CB_INTERFACE_CALLBACK_BASE +void CStubHeaderGenerator::GenInterfaceCallbackBase(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CALLBACK_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +std::string CStubHeaderGenerator::GenMethodParams(const Interface& iface, + const Declaration& decl) { + std::string params; + for (const auto& p : decl.GetParameters()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, iface) + + p->GetID(); + } + + return params; +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_BASE +void CStubHeaderGenerator::GenInterfaceMethodCallbackBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string code(ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_BASE, { + { "", GetReturnTypeString(decl.GetType()) }, + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenMethodParams(iface, decl) } + })); + + stream << SmartIndent(code); +} + +void CStubHeaderGenerator::GenInterfaces(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + + const Interface &iface = static_cast(*i); + GenInterface(stream, iface); + } +} + +void CStubHeaderGenerator::GenInterface(std::ofstream& stream, + const Interface& iface) { + GenInterfaceContextBase(stream, iface); + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() != Declaration::MethodType::DELEGATE) + continue; + + GenInterfaceDelegateBase(stream, iface, *d); + } + + GenInterfaceBase(stream, iface); +} + +// @see #CB_INTERFACE_CONTEXT_BASE +void CStubHeaderGenerator::GenInterfaceContextBase(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_CONTEXT_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() } + })); + + stream << SmartIndent(code); +} + +std::string CStubHeaderGenerator::GenDelegateParams(const Interface& iface, + const Declaration& decl) { + std::string params; + for (const auto& p : decl.GetParameters()) { + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, iface) + + p->GetID(); + } + + return params; +} + +// @see #CB_INTERFACE_DELEGATE_BASE +void CStubHeaderGenerator::GenInterfaceDelegateBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string code(ReplaceAll(CB_INTERFACE_DELEGATE_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenDelegateParams(iface, decl) } + })); + + stream << SmartIndent(code); +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_DECL +std::string CStubHeaderGenerator::GenMethodCallbackDecls(const Interface& iface) { + std::string method_callback_decls; + for (const auto& d : iface.GetDeclarations()) { + if (d->GetMethodType() == Declaration::MethodType::DELEGATE) + continue; + + std::string method_callback_decl(ReplaceAll( + CB_INTERFACE_METHOD_CALLBACK_DECL, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", d->GetID() } + })); + + method_callback_decl = RemoveLine(method_callback_decl); + method_callback_decls += RemoveLine(method_callback_decl, 2); + } + + return method_callback_decls; +} + +// @see #CB_INTERFACE_BASE +void CStubHeaderGenerator::GenInterfaceBase(std::ofstream& stream, + const Interface& iface) { + std::string code(ReplaceAll(CB_INTERFACE_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", GenMethodCallbackDecls(iface) } + })); + + stream << SmartIndent(code); +} + +} // namespace version2 +} // namespace tidl diff --git a/idlc/gen/version2/c_stub_header_generator.hh b/idlc/gen/version2/c_stub_header_generator.hh new file mode 100644 index 0000000..edfd88c --- /dev/null +++ b/idlc/gen/version2/c_stub_header_generator.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_C_GEN_C_STUB_HEADER_GENERATOR_HH_ +#define IDLC_C_GEN_C_STUB_HEADER_GENERATOR_HH_ + +#include +#include + +#include "idlc/gen/version2/c_header_generator_base.hh" + +namespace tidl { +namespace version2 { + +class CStubHeaderGenerator : public CHeaderGeneratorBase { + public: + explicit CStubHeaderGenerator(std::shared_ptr doc); + virtual ~CStubHeaderGenerator() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + + private: + void GenInterfaceHandles(std::ofstream& stream); + void GenInterfaceContextHandle(std::ofstream& stream, const Interface& iface); + void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + + void GenInterfaceCallbacks(std::ofstream& stream); + void GenInterfaceCallbackBase(std::ofstream& stream, const Interface& iface); + void GenInterfaceMethodCallbackBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl); + + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + + void GenInterfaceContextBase(std::ofstream& stream, const Interface& iface); + void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + void GenInterfaceBase(std::ofstream& stream, const Interface& iface); + + std::string GenDelegateParams(const Interface& iface, + const Declaration& decl); + std::string GenMethodParams(const Interface& iface, const Declaration& decl); + std::string GenMethodCallbackDecls(const Interface& iface); +}; + +} // namespace version2 +} // namespace tidl + +#endif // IDLC_C_GEN_C_STUB_HEADER_GENERATOR_HH_ \ No newline at end of file diff --git a/idlc/gen/version2/c_stub_header_generator_cb.hh b/idlc/gen/version2/c_stub_header_generator_cb.hh new file mode 100644 index 0000000..2258e7a --- /dev/null +++ b/idlc/gen/version2/c_stub_header_generator_cb.hh @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_C_GEN_C_STUB_HEADER_GENERATOR_CB_H_ +#define IDLC_C_GEN_C_STUB_HEADER_GENERATOR_CB_H_ + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_HANDLE[] = +R"__c_cb( +/** + * @brief The __context handle. + */ +typedef struct __context_s *__context_h; +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CONTEXT_BASE[] = +R"__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); + +/** + * @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); + +/** + * @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); + +/** + * @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); + +/** + * @brief Disconnects from the proxy. + * + * @param[in] context 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 + */ +int __context_disconnect(__context_h context); +)__c_cb"; + +/** + * 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( +/** + * @brief The __ handle. + */ +typedef struct ___s *___h; +)__c_cb"; + +/** + * 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( +/** + * @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); + +/** + * @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"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_CALLBACK_BASE[] = +R"__c_cb( +/** + * @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"; + +/** + * 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( +/** + * @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"; + +/** + * 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( +/** + * @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"; + +/** + * 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( +___cb ; /**< This callback function is invoked when the request is delivered. */ +)__c_cb"; + +#endif // IDLC_C_GEN_C_STUB_HEADER_GENERATOR_CB_H_ \ No newline at end of file diff --git a/idlc/main.cc b/idlc/main.cc index 889eca5..839f803 100644 --- a/idlc/main.cc +++ b/idlc/main.cc @@ -40,6 +40,8 @@ #include "idlc/gen/dart_stub_gen.h" #include "idlc/gen/version2/c_proxy_header_generator.hh" #include "idlc/gen/version2/c_proxy_body_generator.hh" +#include "idlc/gen/version2/c_stub_header_generator.hh" +#include "idlc/gen/version2/c_stub_body_generator.hh" #include "idlc/gen/version2/c_group_header_generator.hh" #include "idlc/gen/version2/c_group_body_generator.hh" #include "idlc/gen_cion/c_cion_proxy_header_gen.h" @@ -243,14 +245,29 @@ void GenerateStubCodes(std::shared_ptr options, switch (options->GetLanguage()) { case tidl::Options::LANGUAGE_TYPE_C: { - 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"); + if (ps.GetVersion() == 2) { + tidl::version2::CStubHeaderGenerator stub_header(ps.GetDoc()); + stub_header.EnableNamespace(options->HasNamespace()); + stub_header.SetChannelType( + static_cast(options->GetType())); + stub_header.EnableProxy(false); + stub_header.Run(options->GetOutput() + ".h"); + tidl::version2::CStubBodyGenerator stub_body(ps.GetDoc(), options); + stub_body.EnableNamespace(options->HasNamespace()); + stub_body.SetChannelType( + static_cast(options->GetType())); + stub_body.EnableProxy(false); + stub_body.Run(options->GetOutput() + ".c"); + } else { + 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; } case tidl::Options::LANGUAGE_TYPE_CPP: @@ -452,11 +469,15 @@ void GenerateProxyCodes(std::shared_ptr options, tidl::version2::CProxyHeaderGenerator proxy_header(ps.GetDoc()); proxy_header.EnableNamespace(options->HasNamespace()); proxy_header.EnableProxy(true); + proxy_header.SetChannelType( + static_cast(options->GetType())); proxy_header.Run(options->GetOutput() + ".h"); tidl::version2::CProxyBodyGenerator proxy_body(ps.GetDoc(), options); proxy_body.EnableNamespace(options->HasNamespace()); proxy_body.EnableProxy(true); + proxy_body.SetChannelType( + static_cast(options->GetType())); proxy_body.Run(options->GetOutput() + ".c"); } else { tidl::CProxyHeaderGen proxy_header(ps.GetDoc());