From e0d491c2ba43be0b0f143368014f5ce90d6db7d8 Mon Sep 17 00:00:00 2001 From: "jh9216.park" Date: Thu, 14 Jul 2022 01:34:58 -0400 Subject: [PATCH] Implement C group generator Change-Id: Ic6aff811dd557b37aa01ccd35006456ec99d2410 Signed-off-by: jh9216.park --- Makefile.dibs | 2 + idlc/gen/c_gen_base.h | 4 +- idlc/gen/c_group_body_gen.cc | 530 ++++++++++++++++++++++++++++++++++++ idlc/gen/c_group_body_gen.h | 81 ++++++ idlc/gen/c_group_body_gen_cb.h | 562 +++++++++++++++++++++++++++++++++++++++ idlc/gen/c_group_header_gen.cc | 186 +++++++++++++ idlc/gen/c_group_header_gen.h | 55 ++++ idlc/gen/c_group_header_gen_cb.h | 155 +++++++++++ idlc/main.cc | 10 + tests/build_tests/CMakeLists.txt | 1 + tests/build_tests/prebuild.sh | 3 + 11 files changed, 1587 insertions(+), 2 deletions(-) create mode 100644 idlc/gen/c_group_body_gen.cc create mode 100644 idlc/gen/c_group_body_gen.h create mode 100644 idlc/gen/c_group_body_gen_cb.h create mode 100644 idlc/gen/c_group_header_gen.cc create mode 100644 idlc/gen/c_group_header_gen.h create mode 100644 idlc/gen/c_group_header_gen_cb.h diff --git a/Makefile.dibs b/Makefile.dibs index d62cd68..1f58b15 100644 --- a/Makefile.dibs +++ b/Makefile.dibs @@ -18,6 +18,8 @@ SRC_FILES := \ idlc/gen/c_proxy_header_gen.cc \ idlc/gen/c_stub_body_gen.cc \ idlc/gen/c_stub_header_gen.cc \ + idlc/gen/c_group_body_gen.cc \ + idlc/gen/c_group_header_gen.cc \ idlc/gen/cpp_gen_base.cc \ idlc/gen/cpp_proxy_body_gen.cc \ idlc/gen/cpp_proxy_header_gen.cc \ diff --git a/idlc/gen/c_gen_base.h b/idlc/gen/c_gen_base.h index 282e481..eb49512 100644 --- a/idlc/gen/c_gen_base.h +++ b/idlc/gen/c_gen_base.h @@ -54,9 +54,9 @@ class CGeneratorBase : public Generator { const std::map>& GetStructures(); void GenVersion(std::ofstream& stream); - void GenIncludeDefaultHeaders(std::ofstream& stream, bool body = true); + virtual void GenIncludeDefaultHeaders(std::ofstream& stream, bool body = true); void GenGNUSourceDefinition(std::ofstream& stream); - std::string GetHandlePrefix(); + virtual std::string GetHandlePrefix(); std::string RemoveLastSpaces(const std::string& str); private: diff --git a/idlc/gen/c_group_body_gen.cc b/idlc/gen/c_group_body_gen.cc new file mode 100644 index 0000000..69b2ff9 --- /dev/null +++ b/idlc/gen/c_group_body_gen.cc @@ -0,0 +1,530 @@ +/* + * Copyright (c) 2022 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/c_group_body_gen.h" + +namespace { +#include "idlc/gen/c_group_body_gen_cb.h" + +constexpr const char PREFIX_RPC_PORT_GROUP[] = "rpc_port_group"; +} + +namespace tidl { + +CGroupBodyGen::CGroupBodyGen(std::shared_ptr doc) + : CBodyGeneratorBase(doc) { +} + +void CGroupBodyGen::OnInitGen(std::ofstream& stream) { + GenVersion(stream); + GenGNUSourceDefinition(stream); + GenIncludeDefaultHeaders(stream, true); + GenIncludeHeader(stream); + GenLogTag(stream, std::string("RPC_PORT_GROUP")); + GenLogDefinition(stream); + GenVersionDefinition(stream); + GenBaseDefinition(stream); + GenInterfaceMethodHandlerType(stream); + GenInterfaceEnums(stream); + GenStructureDefs(stream); + GenInterfaceDefs(stream); + GenHelper(stream); + GenStructures(stream); + GenInterfaces(stream); +} + +void CGroupBodyGen::OnFiniGen(std::ofstream& stream) { +} + +std::string CGroupBodyGen::GetHandlePrefix() { + std::string prefix = PREFIX_RPC_PORT_GROUP; + if (!HasNamespace()) + return prefix; + + return prefix + "_" + GetFileNamespace(); +} + +void CGroupBodyGen::GenIncludeDefaultHeaders(std::ofstream& stream, bool body) { + CGeneratorBase::GenIncludeDefaultHeaders(stream, body); + stream << CB_INTERFACE_EXTRA_HEADER; +} + +void CGroupBodyGen::GenHelper(std::ofstream& stream) { + stream << SmartIndent(CB_HELPER); +} + +void CGroupBodyGen::GenInterfaceDefs(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_INTERFACE) + continue; + + const Interface &iface = static_cast(*i); + GenInterfaceDef(stream, iface); + } +} + +void CGroupBodyGen::GenInterfaceDef(std::ofstream& stream, + const Interface& iface) { + ReplaceAll(CB_INTERFACE_BASE_DEF) + .Change("", GetHandlePrefix()) + .Change("", iface.GetID()) + .Transform([&](std::string code) { + return SmartIndent(code); + }) + .Out(stream); +} + +void CGroupBodyGen::GenInterfaceEnums(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + GenInterfaceEnum(stream, iface); + } +} + +// @see #CB_INTERFACE_METHOD_ENUM +std::string CGroupBodyGen::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()) { + 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; +} + +void CGroupBodyGen::GenInterfaceEnum(std::ofstream& stream, + const Interface& iface) { + ReplaceAll(CB_INTERFACE_METHOD_ENUM_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", GenMethodEnums(iface) } + }) + .Transform([&](std::string str){ + return SmartIndent(str); + }) + .Out(stream); +} + +void CGroupBodyGen::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 CGroupBodyGen::GenInterface(std::ofstream& stream, const Interface& iface) { + for (const auto& d : iface.GetDeclarations()) { + GenInterfaceMethodHandlerBase(stream, iface, *d); + } + + GenInterfaceMethodTable(stream, iface); + GenInterfaceBase(stream, iface); + + for (const auto& d : iface.GetDeclarations()) { + GenInterfaceMethodBase(stream, iface, *d); + } +} + +// @see #CB_INTERFACE_METHOD_TABLE +void CGroupBodyGen::GenInterfaceMethodTable(std::ofstream& stream, + const Interface& iface) { + ReplaceAll(CB_INTERFACE_METHOD_TABLE, { + { "", iface.GetID() }, + { "", GenMethodHandlers(iface) } + }) + .Transform([&](std::string str){ + return SmartIndent(str); + }) + .Out(stream); +} + +// @see #CB_INTERFACE_METHOD_HANDLER +std::string CGroupBodyGen::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_BASE +void CGroupBodyGen::GenInterfaceBase(std::ofstream& stream, + const Interface& iface) { + std::string prefix = GetHandlePrefix(); + std::string name = iface.GetID(); + ReplaceAll(CB_INTERFACE_BASE) + .Change("", prefix) + .Change("", name) + .Transform([&](std::string str) { + return SmartIndent(str); + }) + .Out(stream); +} + +// @see #CB_INTERFACE_METHOD_HANDLER_TYPE +void CGroupBodyGen::GenInterfaceMethodHandlerType(std::ofstream& stream) { + stream << SmartIndent(CB_INTERFACE_METHOD_HANDLER_TYPE); +} + +// @see #CB_INTERFACE_METHOD_HANDLER_BASE +void CGroupBodyGen::GenInterfaceMethodHandlerBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + ReplaceAll(CB_INTERFACE_METHOD_HANDLER_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenMethodHandlerArgsDecl(iface, decl) }, + { "", + GenMethodHandlerParcelRead(iface, decl) }, + { "", + GenMethodHandlerCallbackInvoke(decl) }, + { "", GenMethodHandlerArgsFree(iface, decl) } + }) + .Transform([&](std::string str){ + return SmartIndent(str); + }) + .Out(stream); +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_INVOKE +std::string CGroupBodyGen::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; + bool first = true; + for (const auto& p : decl.GetParameters()) { + if (!first) + args += ", "; + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) + args += "&"; + + args += p->GetID(); + first = false; + } + code = ReplaceAll(code, "", args); + + return RemoveLine(code); +} + +// @see #CB_INTERFACE_METHOD_DELEGATE_PARCEL_READ +// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_READ +std::string CGroupBodyGen::GenMethodHandlerParcelRead(const Interface& iface, + const Declaration& decl) { + std::string code; + for (const auto& p : decl.GetParameters()) { + std::string parcel_read_code; + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) + continue; + + auto& type = param_type.GetBaseType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_read_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ, "", + GetHandlePrefix()); + parcel_read_code = ReplaceAll(parcel_read_code, "", + GetFullNameFromType(type, iface)); + parcel_read_code = ReplaceAll(parcel_read_code, "", p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ, + "", p->GetID()); + } else if (type.ToString() == "string") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ, + "", p->GetID()); + } else { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ, + "", GetParcelType(type)); + parcel_read_code = ReplaceAll(parcel_read_code, "", p->GetID()); + } + + code += parcel_read_code; + } + + return RemoveLine(code); +} + +std::string CGroupBodyGen::GenMethodHandlerArgsDecl(const Interface& iface, + const Declaration& decl) { + std::string args_decl; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + args_decl += GetArgTypeString(type, iface) + p->GetID() + " = " + + GetErrorValue(type) + ";" + NLine(1); + } + + if (decl.GetMethodType() == Declaration::MethodType::SYNC) { + args_decl += "rpc_port_parcel_h parcel_;" + NLine(1); + args_decl += GetArgTypeString(decl.GetType(), iface) + "res_ = " + + GetErrorValue(decl.GetType()) + ";" + NLine(1); + } + + return args_decl; +} + +// @see #CB_INTERFACE_METHOD_USER_DEFINED_FREE +// @see #CB_INTERFACE_METHOD_BUNDLE_FREE +// @see #CB_INTERFACE_METHOD_STRING_FREE +std::string CGroupBodyGen::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 (type.ToString() == "bundle") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_FREE, + "", p->GetID()); + } else if (type.ToString() == "string") { + free_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_FREE, + "", p->GetID()); + } else { + free_code.clear(); + } + + code += free_code; + } + + return RemoveLine(code); +} + +std::string CGroupBodyGen::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_USER_DEFINED_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_WRITE +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_WRITE +std::string CGroupBodyGen::GenMethodParcelWrite(const Interface& iface, + const Declaration& decl) { + std::string code; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::IN) + continue; + + std::string parcel_write_code; + auto& type = param_type.GetBaseType(); + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + parcel_write_code = ReplaceAll( + CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE, "", + p->GetID()); + std::string name = GetFullNameFromType(type, iface); + parcel_write_code += GetPrivateSharingString(type, iface, "h->port", + p->GetID()); + } else if (type.ToString() == "bundle") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "string") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", p->GetID()); + } else if (type.ToString() == "file") { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_WRITE, + "", p->GetID()); + parcel_write_code += GetPrivateSharingString(type, iface, "h->port", + p->GetID()); + } else { + parcel_write_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_WRITE, + "", GetParcelType(type)); + parcel_write_code = ReplaceAll(parcel_write_code, "", + p->GetID()); + } + + code += parcel_write_code; + } + + return RemoveLine(code); +} + +std::string CGroupBodyGen::GenMethodParamsCheck(const Interface& iface, + const Declaration& decl) { + std::string params_check; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + if (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_METHOD_ASYNC_BASE +std::string CGroupBodyGen::GenMethodAsyncBase(const Interface& iface, + const Declaration& decl) { + std::string prefix = GetHandlePrefix(); + std::string name = iface.GetID(); + std::string method_name = decl.GetID(); + std::string code(ReplaceAll(CB_INTERFACE_METHOD_ASYNC_BASE) + .Change("", prefix) + .Change("", name) + .Change("", method_name) + .Change("", GenMethodParams(iface, decl)) + .Change("", GenMethodParamsCheck(iface, decl)) + .ChangeToUpper("", prefix) + .ChangeToUpper("", name) + .ChangeToUpper("", method_name) + .Change("", GenMethodParcelWrite(iface, decl))); + + return code; +} + +std::string CGroupBodyGen::GenMethodArgs(const Interface& iface, + const Declaration& decl) { + std::string args_code; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::OUT) + continue; + + auto& type = param_type.GetBaseType(); + args_code += GetReturnTypeString(type) + "new_" + p->GetID() + ";"; + args_code += NLine(1); + } + + return args_code; +} + +// @see #CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ +// @see #CB_INTERFACE_METHOD_STRING_PARCEL_READ +// @see #CB_INTERFACE_METHOD_BASE_PARCEL_READ +std::string CGroupBodyGen::GenMethodParcelReadBase(const Interface& iface, + const BaseType& type, const std::string& param_name) { + std::string parcel_read_code; + + if (type.ToString() == "bundle") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ, + "", param_name); + } else if (type.ToString() == "string") { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_STRING_PARCEL_READ, + "", param_name); + } else { + parcel_read_code = ReplaceAll(CB_INTERFACE_METHOD_BASE_PARCEL_READ, + "", GetParcelType(type)); + parcel_read_code = ReplaceAll(parcel_read_code, "", + param_name); + } + + return parcel_read_code; +} + +// @see #CB_INTERFACE_METHOD_VALUE_SET +std::string CGroupBodyGen::GenMethodParcelRead(const Interface& iface, + const Declaration& decl) { + std::string code; + std::string parcel_read_code; + for (const auto& p : decl.GetParameters()) { + auto& param_type = p->GetParameterType(); + if (param_type.GetDirection() != ParameterType::Direction::OUT) + continue; + + auto& type = param_type.GetBaseType(); + code += GenMethodParcelReadBase(iface, type, "new_" + p->GetID()); + code += ReplaceAll(CB_INTERFACE_METHOD_PARAM_SET, "", + p->GetID()); + } + + // Return Value + auto& base_type = decl.GetType(); + code += GenMethodParcelReadBase(iface, base_type, "ret_"); + return RemoveLine(code); +} + +void CGroupBodyGen::GenInterfaceMethodBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + std::string code = GenMethodAsyncBase(iface, decl); + stream << SmartIndent(code); +} + +} // namespace tidl diff --git a/idlc/gen/c_group_body_gen.h b/idlc/gen/c_group_body_gen.h new file mode 100644 index 0000000..18f0473 --- /dev/null +++ b/idlc/gen/c_group_body_gen.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_GEN_C_GROUP_BODY_GEN_H_ +#define IDLC_GEN_C_GROUP_BODY_GEN_H_ + +#include +#include + +#include "idlc/gen/c_body_gen_base.h" +#include "idlc/options.h" + +namespace tidl { + +class CGroupBodyGen : public CBodyGeneratorBase { + public: + explicit CGroupBodyGen(std::shared_ptr doc); + virtual ~CGroupBodyGen() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + std::string GetHandlePrefix() override; + void GenIncludeDefaultHeaders(std::ofstream& stream, bool body) override; + + private: + void GenInterfaceDefs(std::ofstream& stream); + void GenInterfaceDef(std::ofstream& stream, const Interface& iface); + void GenInterfaceMethodHandlerType(std::ofstream& stream); + void GenInterfaceMethodHandlerBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl); + std::string GenMethodHandlerArgsDecl(const Interface& iface, + const Declaration& decl); + std::string GenMethodHandlerArgsFree(const Interface& iface, + const Declaration& decl); + void GenInterfaceMethodTable(std::ofstream& stream, + const Interface& iface); + std::string GenMethodHandlerCallbackInvoke(const Declaration& decl); + std::string GenMethodHandlerParcelRead(const Interface& iface, + const Declaration& decl); + std::string GenMethodHandlers(const Interface& iface); + std::string GenMethodEnums(const Interface& iface); + void GenInterfaceEnums(std::ofstream& stream); + void GenInterfaceEnum(std::ofstream& stream, const Interface& iface); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + void GenInterfaceBase(std::ofstream& stream, const Interface& iface); + void GenInterfaceMethodEnumBase(std::ofstream& stream, const Interface& iface); + void GenInterfaceMethodBase(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + + std::string GenMethodAsyncBase(const Interface& iface, const Declaration& decl); + std::string GenMethodParams(const Interface& iface, const Declaration& decl); + bool GenMethodParamsFileCheck(const Interface& iface, + const Declaration& decl); + std::string GenMethodParcelWrite(const Interface& iface, + const Declaration& decl); + std::string GenMethodArgs(const Interface& iface, const Declaration& decl); + std::string GenMethodParcelReadBase(const Interface& iface, + const BaseType& type, const std::string& param_name); + std::string GenMethodParcelRead(const Interface& iface, + const Declaration& decl); + std::string GenMethodParamsCheck(const Interface& iface, const Declaration& decl); + void GenHelper(std::ofstream& stream); +}; + +} // namespace tidl + +#endif // IDLC_GEN_C_GROUP_BODY_GEN_H_ \ No newline at end of file diff --git a/idlc/gen/c_group_body_gen_cb.h b/idlc/gen/c_group_body_gen_cb.h new file mode 100644 index 0000000..f52d3c4 --- /dev/null +++ b/idlc/gen/c_group_body_gen_cb.h @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_GEN_C_GROUP_BODY_GEN_CB_H_ +#define IDLC_GEN_C_GROUP_BODY_GEN_CB_H_ + + +constexpr const char CB_INTERFACE_METHOD_HANDLER_TYPE[] = +R"__c_cb( +typedef int (*rpc_port_group_method_handler)(rpc_port_parcel_h parcel, 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 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; + int id; + int seq_id; + bool once; + ___cb callback; + void *user_data; +} ___t; +)__c_cb"; + +/** + * The enumeration value. + * The prefix of the interface. + * The name of the interface. + * The name of the delegate of the interface. + */ +constexpr const char CB_INTERFACE_DELEGATE_TABLE_MEMBER[] = +R"__c_cb( +[] = _____delegate_handler, +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_BASE_DEF[] = +R"__c_cb( +typedef struct __s { + __callback_s callback; + event_handler_h event_handler; + GRecMutex mutex; + void *user_data; +} __t; +)__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_parcel_h parcel, void *user_data) +{ + __t *h = user_data; + int ret_ = RPC_PORT_ERROR_NONE; + + + if (h == nullptr) { + _E("Invalid parameter"); + ret_ = RPC_PORT_ERROR_INVALID_PARAMETER; + goto out; + } + + + + out: + + return ret_; +} +)__c_cb"; + +constexpr const char CB_HELPER[] = +R"__c_cb( +static rpc_port_parcel_h __get_parcel_from_bundle(bundle *b) +{ + void *raw = nullptr; + unsigned int size = 0; + rpc_port_parcel_h p; + + int ret = bundle_get_byte(b, "TIDL_RAW", &raw, &size); + if (ret != BUNDLE_ERROR_NONE) + return nullptr; + + ret = rpc_port_parcel_create_from_raw(&p, raw, size); + if (ret != RPC_PORT_ERROR_NONE) + return nullptr; + + return p; +} + +static bundle *__get_bundle_from_parcel(rpc_port_parcel_h p, bundle* b) +{ + void *raw = nullptr; + unsigned int size = 0; + + int ret = rpc_port_parcel_get_raw(p, &raw, &size); + if (ret != RPC_PORT_ERROR_NONE) + return nullptr; + + ret = bundle_add_byte(b, "TIDL_RAW", raw, size); + if (ret != BUNDLE_ERROR_NONE) + return nullptr; + + return b; +} + +static const char *__get_appid() +{ + static char *str = nullptr; + + if (str) + return str; + + char *id = nullptr; + int ret = app_get_id(&id); + if (ret != APP_ERROR_NONE) + id = strdup("system"); + + str = id; + return str; +} + +static char *__get_event_name(const char *appid, const char *iface_name) +{ + size_t size = strlen(appid) + strlen(iface_name) + 19; + char *buf = calloc(1, size); + if (!buf) + return nullptr; + snprintf(buf, size, "event.%s.tidl_iface_%s", appid, iface_name); + return buf; +} +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_BASE[] = +R"__c_cb( + +static void ___event_system_cb(const char *event_name, bundle *event_data, void *user_data) +{ + __t *handle = (__t *)(user_data); + rpc_port_parcel_h p = __get_parcel_from_bundle(event_data); + if (p == nullptr) { + _E("Invalid bundle"); + return; + } + + rpc_port_parcel_h header; + int seq_num = -1; + int cmd; + rpc_port_parcel_get_header(p, &header); + rpc_port_parcel_header_get_seq_num(header, &seq_num); + + _W("[Sequence] %d", seq_num); + rpc_port_parcel_read_int32(p, &cmd); + if (cmd > 1 && cmd < ARRAY_SIZE(___method_table)) { + if (___method_table[cmd]) + ___method_table[cmd](p, handle); + } else { + _W("Invalid protocol. cmd(%d)", cmd); + } + + rpc_port_parcel_destroy(p); +} + +int __create(const char *sender_appid, __callback_s *callback, void *user_data, __h *h) +{ + __t *handle; + int ret; + char *ev_name; + + if (sender_appid == nullptr || callback == nullptr || 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; + } + + g_rec_mutex_init(&handle->mutex); + handle->callback = *callback; + handle->user_data = user_data; + + ev_name = __get_event_name(sender_appid, ""); + if (ev_name == nullptr) + return RPC_PORT_ERROR_OUT_OF_MEMORY; + + ret = event_add_event_handler(ev_name, ___event_system_cb, handle, &handle->event_handler); + free(ev_name); + + if (ret != EVENT_ERROR_NONE) { + _E("Failed to register events. result(%d)", ret); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + *h = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __create_for_sender(__h *h) +{ + __t *handle; + + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + handle = calloc(1, sizeof(__t)); + if (handle == nullptr) { + _E("Out of memory"); + return RPC_PORT_ERROR_OUT_OF_MEMORY; + } + + g_rec_mutex_init(&handle->mutex); + *h = handle; + + return RPC_PORT_ERROR_NONE; +} + +int __destroy(__h h) +{ + if (h == nullptr) { + _E("Invalid parameter"); + return RPC_PORT_ERROR_INVALID_PARAMETER; + } + + g_rec_mutex_lock(&h->mutex); + g_rec_mutex_unlock(&h->mutex); + g_rec_mutex_clear(&h->mutex); + + if (h->event_handler) + event_remove_event_handler(h->event_handler); + + free(h); + + return RPC_PORT_ERROR_NONE; +} +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + * The method name of the interface. + * The parameters of the method of the interface + * The parameters check of the method. + * The uppercase prefix of the interface. + * The uppercase name of the interface. + * The uppercase method name of the interface. + * The implementation to write arguments to the parcel. + */ +constexpr const char CB_INTERFACE_METHOD_ASYNC_BASE[] = +R"__c_cb( +void __invoke_(__h h) +{ + rpc_port_parcel_h parcel_; + rpc_port_parcel_header_h header_; + int seq_num_ = -1; + int res_; + bundle* b; + + if (h == nullptr) { + _E("Invalid parameter"); + set_last_result(RPC_PORT_ERROR_INVALID_PARAMETER); + return; + } + + g_rec_mutex_lock(&h->mutex); + res_ = rpc_port_parcel_create(&parcel_); + if (res_ != RPC_PORT_ERROR_NONE) { + _E("Failed to create parcel handle. error(%d)", res_); + g_rec_mutex_unlock(&h->mutex); + set_last_result(res_); + return; + } + + rpc_port_parcel_get_header(parcel_, &header_); + rpc_port_parcel_header_set_tag(header_, TIDL_VERSION); + rpc_port_parcel_header_get_seq_num(header_, &seq_num_); + _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_); + + rpc_port_parcel_write_int32(parcel_, __METHOD_); + + + b = bundle_create(); + if (__get_bundle_from_parcel(parcel_, b) == nullptr) { + _E("Failed to make bundle from parcel"); + bundle_free(b); + g_rec_mutex_unlock(&h->mutex); + set_last_result(RPC_PORT_ERROR_OUT_OF_MEMORY); + return; + } + + int ret = event_publish_app_event(__get_event_name(__get_appid(), ""), b); + if (ret != EVENT_ERROR_NONE) { + _E("Failed to publish event. result(%d)", ret); + bundle_free(b); + g_rec_mutex_unlock(&h->mutex); + set_last_result(RPC_PORT_ERROR_IO_ERROR); + return; + } + + bundle_free(b); + g_rec_mutex_unlock(&h->mutex); + set_last_result(RPC_PORT_ERROR_NONE); +} +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write(parcel_, &->parcelable, ); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_bundle(parcel_, ); +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_string(parcel_, ); +)__c_cb"; + +/** + * The type of the parcel. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_WRITE[] = +R"__c_cb( +rpc_port_parcel_write_(parcel_, ); +)__c_cb"; + +/** + * The prefix of the structure. + * The name of the structure. + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_USER_DEFINED_PARCEL_READ[] = +R"__c_cb( + = nullptr; +__create(&); +if ( == nullptr) { + _E("Failed to create handle"); + ret_ = RPC_PORT_ERROR_OUT_OF_MEMORY; + goto out; +} + +rpc_port_parcel_read(parcel, &->parcelable, ); +if (get_last_result() != RPC_PORT_ERROR_NONE) { + _E("Failed to read data"); + __destroy(); + = nullptr; + ret_ = get_last_result(); + goto out; +} +)__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 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 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 (h->callback.) + h->callback.(, h->user_data); +)__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; +} + +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 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_group_method_handler ___method_table[] = { + +}; +)__c_cb"; + +/** + * The argument. + */ +constexpr const char CB_INTERFACE_METHOD_BUNDLE_PARCEL_READ[] = +R"__c_cb( + = nullptr; +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 argument. + */ +constexpr const char CB_INTERFACE_METHOD_STRING_PARCEL_READ[] = +R"__c_cb( + = nullptr; +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 argument. + */ +constexpr const char CB_INTERFACE_METHOD_BASE_PARCEL_READ[] = +R"__c_cb( +rpc_port_parcel_read_(parcel, &); +)__c_cb"; + +/** + * The name of the parameter. + */ +constexpr const char CB_INTERFACE_METHOD_PARAM_SET[] = +R"__c_cb( +* = new_; +)__c_cb"; + +constexpr const char CB_INTERFACE_EXTRA_HEADER[] = +R"__c_cb( +#include +#include +)__c_cb"; + +#endif // IDLC_GEN_C_GROUP_BODY_GEN_CB_H_ diff --git a/idlc/gen/c_group_header_gen.cc b/idlc/gen/c_group_header_gen.cc new file mode 100644 index 0000000..7af7032 --- /dev/null +++ b/idlc/gen/c_group_header_gen.cc @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2022 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/c_group_header_gen.h" + +namespace { +#include "idlc/gen/c_group_header_gen_cb.h" + +constexpr const char PREFIX_RPC_PORT_GROUP[] = "rpc_port_group"; +} + +namespace tidl { + +CGroupHeaderGen::CGroupHeaderGen(std::shared_ptr doc) + : CHeaderGeneratorBase(doc) {} + +void CGroupHeaderGen::OnInitGen(std::ofstream& stream) { + GenVersion(stream); + GenPragmaOnce(stream); + GenIncludeDefaultHeaders(stream, false); + GenExplicitLinkageOpen(stream); + GenStructureHandles(stream); + GenInterfaceHandles(stream); + GenStructures(stream); + GenInterfaceCallbacks(stream); + GenInterfaces(stream); +} + +void CGroupHeaderGen::OnFiniGen(std::ofstream& stream) { + GenExplicitLinkageClose(stream); +} + +std::string CGroupHeaderGen::GetHandlePrefix() { + std::string prefix = PREFIX_RPC_PORT_GROUP; + if (!HasNamespace()) + return prefix; + + return prefix + "_" + GetFileNamespace(); +} + +void CGroupHeaderGen::GenInterfaceHandles(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + GenInterfaceHandle(stream, iface); + } +} + +void CGroupHeaderGen::GenInterfaceCallbacks(std::ofstream& stream) { + for (auto& b : GetDocument().GetBlocks()) { + if (b->GetType() != Block::TYPE_INTERFACE) + continue; + + auto& iface = static_cast(*b); + for (const auto& d : iface.GetDeclarations()) { + GenInterfaceMethodCallbackBase(stream, iface, *d); + } + } +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_BASE +void CGroupHeaderGen::GenInterfaceMethodCallbackBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_BASE, { + { "", GetReturnTypeString(decl.GetType()) }, + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenMethodParams(iface, decl) } + }) + .Transform([&](std::string code) { + return SmartIndent(code); + }) + .Out(stream); +} + +// @see #CB_INTERFACE_HANDLE +void CGroupHeaderGen::GenInterfaceHandle(std::ofstream& stream, + const Interface& iface) { + ReplaceAll(CB_INTERFACE_HANDLE) + .Change("", GetHandlePrefix()) + .Change("", iface.GetID()) + .Transform([&](std::string code) { + return SmartIndent(code); + }) + .Out(stream); +} + +void CGroupHeaderGen::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 CGroupHeaderGen::GenInterface(std::ofstream& stream, + const Interface& iface) { + GenInterfaceBase(stream, iface); + + for (const auto& d : iface.GetDeclarations()) + GenInterfaceMethodBase(stream, iface, *d); +} + +// @see #CB_INTERFACE_BASE +void CGroupHeaderGen::GenInterfaceBase(std::ofstream& stream, + const Interface& iface) { + ReplaceAll(CB_INTERFACE_BASE, { + { "", GetHandlePrefix() }, + { "", iface.GetID()}, + { "", GenMethodCallbackDecls(iface) } + }) + .Transform([&](std::string code) { + return SmartIndent(code); + }) + .Out(stream); +} + +// @see #CB_INTERFACE_METHOD_CALLBACK_DECL +std::string CGroupHeaderGen::GenMethodCallbackDecls(const Interface& iface) { + std::string method_callback_decls; + for (const auto& d : iface.GetDeclarations()) { + 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; +} + +std::string CGroupHeaderGen::GenMethodParams(const Interface& iface, + const Declaration& decl) { + std::string params; + bool first = true; + for (const auto& p : decl.GetParameters()) { + if (!first) + params += ", "; + auto& param_type = p->GetParameterType(); + auto& type = param_type.GetBaseType(); + params += GetParamTypeString(param_type.GetDirection(), type, iface) + + p->GetID(); + first = false; + } + + return params; +} + +// @see #CB_INTERFACE_METHOD_BASE +void CGroupHeaderGen::GenInterfaceMethodBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl) { + ReplaceAll(CB_INTERFACE_METHOD_BASE, { + { "", GetReturnTypeString(decl.GetType()) }, + { "", GetHandlePrefix() }, + { "", iface.GetID() }, + { "", decl.GetID() }, + { "", GenMethodParams(iface, decl) } + }) + .Transform([&](std::string code) { + return SmartIndent(code); + }) + .Out(stream); +} + +} // namespace tidl diff --git a/idlc/gen/c_group_header_gen.h b/idlc/gen/c_group_header_gen.h new file mode 100644 index 0000000..39a846a --- /dev/null +++ b/idlc/gen/c_group_header_gen.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IDLC_GEN_C_GROUP_HEADER_GEN_H_ +#define IDLC_GEN_C_GROUP_HEADER_GEN_H_ + +#include +#include + +#include "idlc/gen/c_header_gen_base.h" + +namespace tidl { + +class CGroupHeaderGen : public CHeaderGeneratorBase { + public: + explicit CGroupHeaderGen(std::shared_ptr doc); + virtual ~CGroupHeaderGen() = default; + + void OnInitGen(std::ofstream& stream) override; + void OnFiniGen(std::ofstream& stream) override; + std::string GetHandlePrefix() override; + + private: + void GenInterfaceHandles(std::ofstream& stream); + void GenInterfaceHandle(std::ofstream& stream, const Interface& iface); + void GenInterfaces(std::ofstream& stream); + void GenInterface(std::ofstream& stream, const Interface& iface); + + void GenInterfaceCallbacks(std::ofstream& stream); + void GenInterfaceMethodCallbackBase(std::ofstream& stream, + const Interface& iface, const Declaration& decl); + std::string GenMethodCallbackDecls(const Interface& iface); + void GenInterfaceBase(std::ofstream& stream, const Interface& iface); + void GenInterfaceMethodBase(std::ofstream& stream, const Interface& iface, + const Declaration& decl); + + std::string GenMethodParams(const Interface& iface, const Declaration& decl); +}; + +} // namespace tidl + +#endif // IDLC_GEN_C_GROUP_HEADER_GEN_H_ \ No newline at end of file diff --git a/idlc/gen/c_group_header_gen_cb.h b/idlc/gen/c_group_header_gen_cb.h new file mode 100644 index 0000000..8305e95 --- /dev/null +++ b/idlc/gen/c_group_header_gen_cb.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2022 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_GROUP_HEADER_GEN_CB_H_ +#define IDLC_C_GROUP_HEADER_GEN_CB_H_ + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_HANDLE[] = +R"__c_cb( +/** + * @brief The _ handle. + */ +typedef struct __s *__h; +)__c_cb"; + +/** + * The prefix of the interface. + * The name of the interface. + */ +constexpr const char CB_INTERFACE_BASE[] = +R"__c_cb( +/** + * @brief The structure type containing the set of callback functions for handling events. + * @details It is one of the input parameters of the __register() function. + * + * @see __create_cb + * @see __terminate_cb + */ +typedef struct { + +} __callback_s; + +/** + * @brief Creates a _ handle. + * @remarks The @a h handle should be released using + * the __destroy() if it's no longer needed. + * + * @param[in] sender_appid ID of app sending events + * @param[in] callback The set of callback functions to handle events + * @param[in] user_data The user data to be passed to the callback function + * @param[out] h The _ 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 + * @retval #RPC_PORT_ERROR_IO_ERROR IO error + + * @see __destroy() + * @see #__callback_s + */ +int __create(const char *sender_appid, __callback_s *callback, void *user_data, __h *h); + +/** + * @brief Creates a _ handle for sending events. + * @remarks The @a h handle should be released using + * the __destroy() if it's no longer needed. + * + * @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 + * @retval #RPC_PORT_ERROR_IO_ERROR IO error + + * @see __destroy() + */ +int __create_for_sender(__h *h); + +/** + * @brief Destroys the _ handle. + * + * @param[in] h The _ handle + * @return @c 0 on success, + * otherwise a negative error value + * @retval #RPC_PORT_ERROR_NONE Successful + * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @see __create() + */ +int __destroy(__h h); + +)__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 payload is received. + * + * @param[in] ... + * @param[in] user_data The user data passed from the registration function + * @see #__callback_s; + */ +typedef (*___cb)(, void *user_data); +)__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"; + +/** + * The type of the return value. + * The prefix of the interface. + * The of the interface. + * The name of the method. + * The parameters of the method. + */ +constexpr const char CB_INTERFACE_METHOD_BASE[] = +R"__c_cb( +/** + * @brief Calls the () method. + * @details The return value and args are decided by the interface declaration. + * You can get the result using get_last_result(). + * Before returning the function, the function sets the result using set_last_result(). + * @remarks The specific error code can be obtained using the get_last_result() function. Error codes are described in Exception section. + * @param[in] h The _ handle + * @param[in] ... + * @exception #RPC_PORT_ERROR_NONE Successful + * @exception #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter + * @exception #RPC_PORT_ERROR_OUT_OF_MEMORY Out of memory + * @exception #RPC_PORT_ERROR_IO_ERROR I/O error + */ +__invoke_(__h h, ); +)__c_cb"; + +#endif // IDLC_C_GROUP_HEADER_GEN_CB_H_ diff --git a/idlc/main.cc b/idlc/main.cc index f6d339c..4df018a 100644 --- a/idlc/main.cc +++ b/idlc/main.cc @@ -27,6 +27,8 @@ #include "idlc/gen/c_proxy_body_gen.h" #include "idlc/gen/c_stub_header_gen.h" #include "idlc/gen/c_stub_body_gen.h" +#include "idlc/gen/c_group_header_gen.h" +#include "idlc/gen/c_group_body_gen.h" #include "idlc/gen/cpp_proxy_header_gen.h" #include "idlc/gen/cpp_proxy_body_gen.h" #include "idlc/gen/cpp_stub_header_gen.h" @@ -327,6 +329,14 @@ void GenerateGroupCodes(std::shared_ptr options, } case tidl::Options::LANGUAGE_TYPE_C: + { + tidl::CGroupHeaderGen group_header(ps.GetDoc()); + group_header.Run(options->GetOutput() + ".h"); + tidl::CGroupBodyGen group_body(ps.GetDoc()); + group_body.Run(options->GetOutput() + ".c"); + break; + } + case tidl::Options::LANGUAGE_TYPE_CSHARP: case tidl::Options::LANGUAGE_TYPE_JAVA: default: diff --git a/tests/build_tests/CMakeLists.txt b/tests/build_tests/CMakeLists.txt index 80cac8f..90386b4 100644 --- a/tests/build_tests/CMakeLists.txt +++ b/tests/build_tests/CMakeLists.txt @@ -63,6 +63,7 @@ SET(TIDL_GEN_SRCS MessageProxyC.c MessageStub.cc FooPubsubGroup.cc + FooPubsubGroupC.c FooPubsubCionGroup.cc FooPubsubCionGroupC.c ) diff --git a/tests/build_tests/prebuild.sh b/tests/build_tests/prebuild.sh index 41e9df6..dd1e304 100755 --- a/tests/build_tests/prebuild.sh +++ b/tests/build_tests/prebuild.sh @@ -45,6 +45,9 @@ GenerateTIDL() { OUTPUT="${FILES_FOR_GROUP[index]}Group" ${TIDLC} -g -l C++ -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT} + + OUTPUT="${FILES_FOR_GROUP[index]}GroupC" + ${TIDLC} -g -l C -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT} done for index in ${!FILES_CION[*]}; do -- 2.7.4