for (auto& block : GetDocument().GetBlocks()) {
if (block->GetType() == Block::TYPE_INTERFACE) {
auto& iface = static_cast<const Interface&>(*block);
+ AddParameterType(
+ std::make_shared<ParameterType>(
+ new BaseType(iface.GetID() + "_remote_exception", "", true),
+ ParameterType::Direction::OUT));
+ AddParameterType(
+ std::make_shared<ParameterType>(
+ new BaseType(iface.GetID() + "_remote_exception", "", true),
+ ParameterType::Direction::IN));
+
for (const auto& decl : iface.GetDeclarations()) {
for (const auto& param : decl->GetParameters()) {
auto& type = param->GetParameterType().GetBaseType();
#include "idlc/gen/version2/c_proxy_body_generator.hh"
+#include <utility>
+
#include "idlc/gen/version2/c_proxy_body_generator_cb.hh"
namespace tidl {
GenInterfaceDelegateDefinition(stream, iface, *decl);
}
+ GenInterfaceRemoteExceptionDefinition(stream, iface);
GenInterfaceBaseDefinition(stream, iface);
}
}
.Out(stream);
}
+void CProxyBodyGenerator::GenInterfaceRemoteExceptionDefinition(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_DEF)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
void CProxyBodyGenerator::GenInterfaceBaseDefinition(std::ofstream& stream,
const Interface& iface) {
ReplaceAll(CB_INTERFACE_BASE_DEF)
GenInterfaceDelegateTable(stream, iface);
GenInterfaceMethodEnumBase(stream, iface);
+ GenInterfaceRemoteExceptionBase(stream, iface);
GenInterfaceBase(stream, iface);
for (const auto& decl : iface.GetDeclarations()) {
.Out(stream);
}
+void CProxyBodyGenerator::GenInterfaceRemoteExceptionBase(std::ofstream& stream,
+ const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_BASE)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
void CProxyBodyGenerator::GenInterfaceMethodEnumBase(std::ofstream& stream,
const Interface& iface) {
std::string enums = GetHandlePrefix() + "_" + iface.GetID() +
const Interface& iface, const Declaration& decl) {
std::string enum_value = GetHandlePrefix() + "_" + iface.GetID() +
"_DELEGATE_" + decl.GetID();
- std::string delegate_args_free = GenDelegateArgsFree(iface, decl);
+ bool has_free = false;
+ std::string delegate_args_free = GenDelegateArgsFree(iface, decl, &has_free);
ReplaceAll(CB_INTERFACE_DELEGATE_BASE)
.Change("<PREFIX>", GetHandlePrefix())
}
std::string CProxyBodyGenerator::GenDelegateArgsFree(const Interface& iface,
- const Declaration& decl) {
+ const Declaration& decl, bool* has_free) {
std::string code;
for (const auto& param : decl.GetParameters()) {
auto& param_type = param->GetParameterType();
.Change("<PREFIX>", GetHandlePrefix())
.Change("<NAME>", GetFullNameFromType(type, iface))
.Change("<ARG>", param->GetID());
+ *has_free = true;
} else if (type.ToString() == "bundle") {
code += ReplaceAll(CB_INTERFACE_DELEGATE_BUNDLE_ARG_FREE,
"<ARG>", param->GetID());
+ *has_free = true;
} else if (type.ToString() == "string" || type.ToString() == "file") {
code += ReplaceAll(CB_INTERFACE_DELEGATE_STRING_ARG_FREE,
"<ARG>", param->GetID());
+ *has_free = true;
}
}
void GenInterfaceDefinition(std::ofstream& stream);
void GenInterfaceDelegateDefinition(std::ofstream& stream,
const Interface& iface, const Declaration& decl);
+ void GenInterfaceRemoteExceptionDefinition(std::ofstream& stream,
+ const Interface& iface);
void GenInterfaceBaseDefinition(std::ofstream& stream,
const Interface& iface);
void GenInterface(std::ofstream& stream);
void GenInterfaceMethodBase(std::ofstream& stream, const Interface& iface,
const Declaration& decl);
void GenInterfaceBase(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionBase(std::ofstream& stream,
+ const Interface& iface);
void GenInterfaceMethodEnumBase(std::ofstream& stream,
const Interface& iface);
void GenInterfaceDelegateTable(std::ofstream& stream, const Interface& iface);
std::string GenDelegateArgsDecl(const Interface& iface,
const Declaration& decl);
std::string GenDelegateArgsFree(const Interface& iface,
- const Declaration& decl);
+ const Declaration& decl, bool* has_free);
void GenInterfaceDelegateEnumBase(std::ofstream& stream,
const Interface& iface);
void GenDelegateDefinition(std::ofstream& stream);
rpc_port_unit_map_read_int(map, "[METHOD]", &cmd);
if (cmd == <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_RESULT_) {
+ if (__<PREFIX>_<NAME>_remote_exception != nullptr)
+ <PREFIX>_<NAME>_remote_exception_destroy(__<PREFIX>_<NAME>_remote_exception);
+
+ __<PREFIX>_<NAME>_remote_exception = nullptr;
+ rpc_port_unit_map_read_<NAME>_remote_exception(map, "[REMOTE_EXCEPTION]", &__<PREFIX>_<NAME>_remote_exception);
+
*unit_map = map;
return;
}
h->delegates = g_list_append(h->delegates, <ARG>);
)__c_cb";
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_remote_exception_s {
+ rpc_port_parcelable_t parcelable;
+ int cause;
+ char *message;
+} <PREFIX>_<NAME>_remote_exception_t;
+
+static __thread <PREFIX>_<NAME>_remote_exception_h __<PREFIX>_<NAME>_remote_exception;
+
+static int <PREFIX>_<NAME>_remote_exception_create(<PREFIX>_<NAME>_remote_exception_h *h);
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_BASE[] =
+R"__c_cb(
+static void __<PREFIX>_<NAME>_remote_exception_to(rpc_port_parcel_h parcel, void *user_data)
+{
+ <PREFIX>_<NAME>_remote_exception_h h = 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, "cause", h->cause);
+ rpc_port_unit_map_write_string(map, "message", h->message);
+ rpc_port_parcel_write(parcel, &map->parcelable, map);
+ rpc_port_unit_map_destroy(map);
+ set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static void __<PREFIX>_<NAME>_remote_exception_from(rpc_port_parcel_h parcel, void *user_data)
+{
+ <PREFIX>_<NAME>_remote_exception_h h = 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, "cause", &h->cause);
+ rpc_port_unit_map_read_string(map, "message", &h->message);
+ rpc_port_unit_map_destroy(map);
+ set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static int <PREFIX>_<NAME>_remote_exception_create(<PREFIX>_<NAME>_remote_exception_h *h)
+{
+ <PREFIX>_<NAME>_remote_exception_h exception;
+
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ exception = calloc(1, sizeof(<PREFIX>_<NAME>_remote_exception_t));
+ if (exception == nullptr) {
+ _E("calloc() is failed");
+ return RPC_PORT_ERROR_OUT_OF_MEMORY;
+ }
+
+ exception->parcelable.to = __<PREFIX>_<NAME>_remote_exception_to;
+ exception->parcelable.from = __<PREFIX>_<NAME>_remote_exception_from;
+
+ *h = exception;
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_get_remote_exception(<PREFIX>_<NAME>_remote_exception_h *h)
+{
+ rpc_port_unit_map_h map;
+ int ret;
+
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ if (__<PREFIX>_<NAME>_remote_exception == nullptr) {
+ _W("There is no exceptions");
+ *h = nullptr;
+ return RPC_PORT_ERROR_NONE;
+ }
+
+ map = rpc_port_unit_map_create();
+ if (map == nullptr) {
+ _E("Failed to create unit map");
+ return RPC_PORT_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = rpc_port_unit_map_write_<NAME>_remote_exception(map, "clone", __<PREFIX>_<NAME>_remote_exception);
+ if (ret != RPC_PORT_ERROR_NONE) {
+ _E("Failed to write remote exception. error(%d)", ret);
+ rpc_port_unit_map_destroy(map);
+ return ret;
+ }
+
+ ret = rpc_port_unit_map_read_<NAME>_remote_exception(map, "clone", h);
+ rpc_port_unit_map_destroy(map);
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remote_exception_get_cause(<PREFIX>_<NAME>_remote_exception_h h, int *cause)
+{
+ if (h == nullptr || cause == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ *cause = h->cause;
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remote_exception_get_message(<PREFIX>_<NAME>_remote_exception_h h, char **message)
+{
+ if (h == nullptr || message == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ *message = strdup(h->message);
+ if (*message == nullptr) {
+ _E("strdup() is failed");
+ return RPC_PORT_ERROR_OUT_OF_MEMORY;
+ }
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remote_exception_destroy(<PREFIX>_<NAME>_remote_exception_h h)
+{
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ if (h->message)
+ free(h->message);
+
+ free(h);
+
+ return RPC_PORT_ERROR_NONE;
+}
+)__c_cb";
+
} // namespace version2
} // namespace tidl
auto& iface = static_cast<const Interface&>(*b);
GenInterfaceHandle(stream, iface);
+ GenInterfaceRemoteExceptionHandle(stream, iface);
for (const auto& d : iface.GetDeclarations()) {
if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
continue;
.Out(stream);
}
+void CProxyHeaderGenerator::GenInterfaceRemoteExceptionHandle(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_HANDLE)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
void CProxyHeaderGenerator::GenInterfaceDelegateHandle(std::ofstream& stream,
const Interface& iface, const Declaration& decl) {
ReplaceAll(CB_INTERFACE_DELEGATE_HANDLE)
GenInterfaceDelegateBase(stream, iface, *d);
}
+ GenInterfaceRemoteExceptionBase(stream, iface);
GenInterfaceBase(stream, iface);
for (const auto& d : iface.GetDeclarations()) {
.Out(stream);
}
+void CProxyHeaderGenerator::GenInterfaceRemoteExceptionBase(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_BASE)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
std::string CProxyHeaderGenerator::GenDelegateParams(const Interface& iface,
const Declaration& decl) {
std::string params;
private:
void GenInterfaceHandles(std::ofstream& stream);
void GenInterfaceHandle(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionHandle(std::ofstream& stream,
+ const Interface& iface);
void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& iface,
const Declaration& decl);
void GenInterfaces(std::ofstream& stream);
void GenInterface(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionBase(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);
<RETURN_TYPE><PREFIX>_<NAME>_invoke_<METHOD_NAME>(<PREFIX>_<NAME>_h h<METHOD_PARAMS>);
)__c_cb";
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_HANDLE[] =
+R"__c_cb(
+/**
+ * @breif The <PREFIX> <NAME> remote exception handle.
+ */
+typedef struct <PREFIX>_<NAME>_remote_exception_s *<PREFIX>_<NAME>_remote_exception_h;
+)__c_cb";
+
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_BASE[] =
+R"__c_cb(
+/**
+ * @brief Gets the remote exception handle.
+ * @details If the return value is nullptr, there is no exceptions.
+ * @remarks The handle should be released using <PREFIX>_<NAME>_remote_exception_destroy(), if it's no longer needed.
+ * @param[out] h The <PREFIX> <NAME> remote exception 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 <PREFIX>_<NAME>_remote_exception_destroy();
+ */
+int <PREFIX>_<NAME>_get_remote_exception(<PREFIX>_<NAME>_remote_exception_h *h);
+
+/**
+ * @brief Gets the cause of the exception.
+ * @param[in] h The <PREFIX> <NAME> remote exception handle.
+ * @param[out] cause The cause
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_remote_exception_get_cause(<PREFIX>_<NAME>_remote_exception_h h, int *cause);
+
+/**
+ * @brief Gets the detail message of the exception.
+ * @remarks The @c message should be released if it's no longer needed.
+ * @param[in] h The <PREFIX> <NAME> remote exception handle.
+ * @param[out] message The detail message
+ * @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 <PREFIX>_<NAME>_remote_exception_get_message(<PREFIX>_<NAME>_remote_exception_h, char **message);
+
+/**
+ * @brief Destroys the remote exception handle.
+ * @param[in] h The <PREFIX> <NAME> remote exception handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_remote_exception_destroy(<PREFIX>_<NAME>_remote_exception_h h);
+)__c_cb";
+
} // namespace version2
} // namespace tidl
GenInterfaceCallbackPortCheckDef(stream, iface);
GenInterfaceContextDef(stream, iface);
+ GenInterfaceRemoteExceptionDefinition(stream, iface);
GenInterfaceBaseDef(stream, iface);
}
stream << SmartIndent(code);
}
+// @see #CB_INTERFACE_REMOTE_EXCEPTION_DEF
+void CStubBodyGenerator::GenInterfaceRemoteExceptionDefinition(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_DEF)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
// @see #CB_INTERFACE_BASE_DEF
void CStubBodyGenerator::GenInterfaceBaseDef(std::ofstream& stream,
const Interface& iface) {
GenInterfaceMethodTable(stream, iface);
GenInterfaceContextBase(stream, iface);
+ GenInterfaceRemoteExceptionBase(stream, iface);
if (has_delegate)
GenInterfaceCallbackPortCheck(stream, iface);
stream << SmartIndent(code);
}
+// @see #CB_INTERFACE_REMOTE_EXCEPTION_BASE
+void CStubBodyGenerator::GenInterfaceRemoteExceptionBase(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_BASE)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
std::string CStubBodyGenerator::GenDelegateParams(const Interface& iface,
const Declaration& decl) {
std::string params;
// @see #CB_INTERFACE_METHOD_CALLBACK_INVOKE
std::string CStubBodyGenerator::GenMethodHandlerCallbackInvoke(
- const Declaration& decl) {
+ const Interface& iface, const Declaration& decl) {
std::string code(ReplaceAll(CB_INTERFACE_METHOD_CALLBACK_INVOKE,
"<METHOD_NAME>", decl.GetID()));
+ code = ReplaceAll(code, "<PREFIX>", GetHandlePrefix());
+ code = ReplaceAll(code, "<NAME>", iface.GetID());
if (decl.GetMethodType() == Declaration::MethodType::SYNC)
code = ReplaceAll(code, "<RES_SET>", "res_ = ");
code += GenMethodUnitMapWriteBase(iface, decl.GetType(), "[RESULT]", "res_");
- code += std::string(CB_INTERFACE_METHOD_PARCEL_WRITE_POST);
+ code += ReplaceAll(CB_INTERFACE_METHOD_PARCEL_WRITE_POST)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID());
return RemoveLine(code);
}
{ "<METHOD_UNIT_MAP_READ>",
GenMethodUnitMapRead(iface, decl) },
{ "<METHOD_HANDLER_CALLBACK_INVOKE>",
- GenMethodHandlerCallbackInvoke(decl) },
+ GenMethodHandlerCallbackInvoke(iface, decl) },
{ "<METHOD_UNIT_MAP_WRITE>",
GenMethodUnitMapWrite(iface, decl) },
{ "<METHOD_HANDLER_ARGS_FREE>", GenMethodHandlerArgsFree(iface, decl) }
void GenInterfaceDefs(std::ofstream& stream);
void GenInterfaceDef(std::ofstream& stream, const Interface& iface);
void GenInterfaceContextDef(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionDefinition(std::ofstream& stream,
+ const Interface& iface);
void GenInterfaceDelegateDef(std::ofstream& stream, const Interface& iface,
const Declaration& decl);
void GenInterfaceCallbackPortCheckDef(std::ofstream& stream,
void GenInterfaces(std::ofstream& stream);
void GenInterface(std::ofstream& stream, const Interface& iface);
void GenInterfaceContextBase(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionBase(std::ofstream& stream,
+ const Interface& iface);
void GenInterfaceDelegateBase(std::ofstream& stream, const Interface& iface,
const Declaration& decl);
void GenInterfaceMethodHandlerBase(std::ofstream& stream,
const Declaration& decl);
std::string GenMethodUnitMapRead(const Interface& iface,
const Declaration& decl);
- std::string GenMethodHandlerCallbackInvoke(const Declaration& decl);
+ std::string GenMethodHandlerCallbackInvoke(const Interface& iface,
+ const Declaration& decl);
std::string GenMethodUnitMapWriteBase(
const Interface& iface, const BaseType& type,
const std::string& arg_name, const std::string& arg);
)__c_cb";
/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
* <RES_SET> The implemention to set the result of the callback function.
* <METHOD_NAME> The name of the method of the interface.
* <METHOD_ARGS> The arguments of the method.
*/
constexpr const char CB_INTERFACE_METHOD_CALLBACK_INVOKE[] =
R"__c_cb(
+if (__<PREFIX>_<NAME>_remote_exception != nullptr) {
+ <PREFIX>_<NAME>_remote_exception_destroy(__<PREFIX>_<NAME>_remote_exception);
+ __<PREFIX>_<NAME>_remote_exception = nullptr;
+}
+
if (context_->callback.<METHOD_NAME>)
<RES_SET>context_->callback.<METHOD_NAME>(context_<METHOD_ARGS>, context_->user_data);
)__c_cb";
rpc_port_unit_map_write_int(map_, "[METHOD]", <UPPERCASE_PREFIX>_<UPPERCASE_NAME>_METHOD_RESULT_);
)__c_cb";
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
constexpr const char CB_INTERFACE_METHOD_PARCEL_WRITE_POST[] =
R"__c_cb(
+if (__<PREFIX>_<NAME>_remote_exception != nullptr)
+ rpc_port_unit_map_write_<NAME>_remote_exception(map_, "[REMOTE_EXCEPTION]", __<PREFIX>_<NAME>_remote_exception);
rpc_port_parcel_write(parcel_, &map_->parcelable, map_);
rpc_port_unit_map_destroy(map_);
}
)__c_cb";
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_DEF[] =
+R"__c_cb(
+typedef struct <PREFIX>_<NAME>_remote_exception_s {
+ rpc_port_parcelable_t parcelable;
+ int cause;
+ char *message;
+} <PREFIX>_<NAME>_remote_exception_t;
+
+static __thread <PREFIX>_<NAME>_remote_exception_h __<PREFIX>_<NAME>_remote_exception;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_BASE[] =
+R"__c_cb(
+static void __<PREFIX>_<NAME>_remote_exception_to(rpc_port_parcel_h parcel, void *user_data)
+{
+ <PREFIX>_<NAME>_remote_exception_h h = 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, "cause", h->cause);
+ rpc_port_unit_map_write_string(map, "message", h->message);
+ rpc_port_parcel_write(parcel, &map->parcelable, map);
+ rpc_port_unit_map_destroy(map);
+ set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+static void __<PREFIX>_<NAME>_remote_exception_from(rpc_port_parcel_h parcel, void *user_data)
+{
+ <PREFIX>_<NAME>_remote_exception_h h = 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, "cause", &h->cause);
+ rpc_port_unit_map_read_string(map, "message", &h->message);
+ rpc_port_unit_map_destroy(map);
+ set_last_result(RPC_PORT_ERROR_NONE);
+}
+
+int <PREFIX>_<NAME>_remote_exception_create(<PREFIX>_<NAME>_remote_exception_h *h)
+{
+ <PREFIX>_<NAME>_remote_exception_h exception;
+
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ exception = calloc(1, sizeof(<PREFIX>_<NAME>_remote_exception_t));
+ if (exception == nullptr) {
+ _E("calloc() is failed");
+ return RPC_PORT_ERROR_OUT_OF_MEMORY;
+ }
+
+ exception->parcelable.to = __<PREFIX>_<NAME>_remote_exception_to;
+ exception->parcelable.from = __<PREFIX>_<NAME>_remote_exception_from;
+
+ *h = exception;
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remote_exception_set_cause(<PREFIX>_<NAME>_remote_exception_h h, int cause)
+{
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ h->cause = cause;
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remote_exception_set_message(<PREFIX>_<NAME>_remote_exception_h h, const char *message)
+{
+ if (h == nullptr || message == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ if (h->message)
+ free(h->message);
+
+ h->message = strdup(message);
+ if (h->message == nullptr) {
+ _E("strdup() is failed");
+ return RPC_PORT_ERROR_OUT_OF_MEMORY;
+ }
+
+ return RPC_PORT_ERROR_NONE;
+}
+
+int <PREFIX>_<NAME>_remote_exception_throw(<PREFIX>_<NAME>_remote_exception_h h)
+{
+ rpc_port_unit_map_h map;
+ int ret;
+
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ map = rpc_port_unit_map_create();
+ if (map == nullptr) {
+ _E("Failed to create unit map");
+ return RPC_PORT_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = rpc_port_unit_map_write_<NAME>_remote_exception(map, "clone", h);
+ if (ret != RPC_PORT_ERROR_NONE) {
+ _E("Failed to write remote exception. error(%d)", ret);
+ rpc_port_unit_map_destroy(map);
+ return ret;
+ }
+
+ if (__<PREFIX>_<NAME>_remote_exception != nullptr) {
+ <PREFIX>_<NAME>_remote_exception_destroy(__<PREFIX>_<NAME>_remote_exception);
+ __<PREFIX>_<NAME>_remote_exception = nullptr;
+ }
+
+ ret = rpc_port_unit_map_read_<NAME>_remote_exception(map, "clone", &__<PREFIX>_<NAME>_remote_exception);
+ rpc_port_unit_map_destroy(map);
+
+ return ret;
+}
+
+int <PREFIX>_<NAME>_remote_exception_destroy(<PREFIX>_<NAME>_remote_exception_h h)
+{
+ if (h == nullptr) {
+ _E("Invalid parameter");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ if (h->message)
+ free(h->message);
+
+ free(h);
+
+ return RPC_PORT_ERROR_NONE;
+}
+)__c_cb";
+
#endif // IDLC_C_GEN_C_STUB_BODY_GENERATOR_CB_H_
auto& iface = static_cast<const Interface&>(*b);
GenInterfaceContextHandle(stream, iface);
+ GenInterfaceRemoteExceptionHandle(stream, iface);
for (const auto& d : iface.GetDeclarations()) {
if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
continue;
stream << SmartIndent(code);
}
+// @see #CB_INTERFACE_REMOTE_EXCEPTION_HANDLE
+void CStubHeaderGenerator::GenInterfaceRemoteExceptionHandle(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_HANDLE)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
// @see #CB_INTERFACE_DELEGATE_HANDLE
void CStubHeaderGenerator::GenInterfaceDelegateHandle(std::ofstream& stream,
const Interface& iface, const Declaration& decl) {
void CStubHeaderGenerator::GenInterface(std::ofstream& stream,
const Interface& iface) {
GenInterfaceContextBase(stream, iface);
+ GenInterfaceRemoteExceptionBase(stream, iface);
for (const auto& d : iface.GetDeclarations()) {
if (d->GetMethodType() != Declaration::MethodType::DELEGATE)
continue;
stream << SmartIndent(code);
}
+// @see #CB_INTERFACE_REMOTE_EXCEPTION_BASE
+void CStubHeaderGenerator::GenInterfaceRemoteExceptionBase(
+ std::ofstream& stream, const Interface& iface) {
+ ReplaceAll(CB_INTERFACE_REMOTE_EXCEPTION_BASE)
+ .Change("<PREFIX>", GetHandlePrefix())
+ .Change("<NAME>", iface.GetID())
+ .Transform([&](std::string code) { return SmartIndent(code); })
+ .Out(stream);
+}
+
std::string CStubHeaderGenerator::GenDelegateParams(const Interface& iface,
const Declaration& decl) {
std::string params;
private:
void GenInterfaceHandles(std::ofstream& stream);
void GenInterfaceContextHandle(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionHandle(std::ofstream& stream,
+ const Interface& iface);
void GenInterfaceDelegateHandle(std::ofstream& stream, const Interface& iface,
const Declaration& decl);
void GenInterface(std::ofstream& stream, const Interface& iface);
void GenInterfaceContextBase(std::ofstream& stream, const Interface& iface);
+ void GenInterfaceRemoteExceptionBase(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);
} // namespace version2
} // namespace tidl
-#endif // IDLC_C_GEN_C_STUB_HEADER_GENERATOR_HH_
\ No newline at end of file
+#endif // IDLC_C_GEN_C_STUB_HEADER_GENERATOR_HH_
<PREFIX>_<NAME>_<METHOD_NAME>_cb <METHOD_NAME>; /**< This callback function is invoked when the <METHOD_NAME> request is delivered. */
)__c_cb";
-#endif // IDLC_C_GEN_C_STUB_HEADER_GENERATOR_CB_H_
\ No newline at end of file
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_HANDLE[] =
+R"__c_cb(
+/**
+ * @brief The <PREFIX> <NAME> remote exception handle.
+ */
+typedef struct <PREFIX>_<NAME>_remote_exception_s *<PREFIX>_<NAME>_remote_exception_h;
+)__c_cb";
+
+/**
+ * <PREFIX> The prefix of the interface.
+ * <NAME> The name of the interface.
+ */
+constexpr const char CB_INTERFACE_REMOTE_EXCEPTION_BASE[] =
+R"__c_cb(
+/**
+ * @brief Creates the <PREFIX> <NAME> remote exception handle.
+ *
+ * @remarks The @c h handle should be released if it's no longer needed.
+ * @param[out] h The <PREFIX> <NAME> remote exception 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 <PREFIX>_<NAME>_remote_exception_throw()
+ * @see <PREFIX>_<NAME>_remote_exception_destroy()
+ */
+int <PREFIX>_<NAME>_remote_exception_create(<PREFIX>_<NAME>_remote_exception_h *h);
+
+/**
+ * @brief Sets the cause of the exception.
+ *
+ * @param[in] h The <PREFIX> <NAME> remote exception handle
+ * @param[in] cause The cause of the exception
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_remote_exception_set_cause(<PREFIX>_<NAME>_remote_exception_h h, int cause);
+
+/**
+ * @brief Sets the detail message of the exception.
+ *
+ * @param[in] h The <PREFIX> <NAME> remote exception handle
+ * @param[in] message The detail message of the exception
+ * @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 <PREFIX>_<NAME>_remote_exception_set_message(<PREFIX>_<NAME>_remote_exception_h h, const char *message);
+
+/**
+ * @brief Throws the exception to the client.
+ * @details This function throws the exception to the client in the callback function.
+ * While calling the registered callback function related the method call, this function should be called
+ * if you want to send the remote exception to the client.
+ * If this function is called outside of the registered callback function, it's meaningless.
+ * The callback function is not returned by calling this function.
+ *
+ * @param[in] h The <PREFIX> <NAME> remote exception 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 <PREFIX>_<NAME>_remote_exception_throw(<PREFIX>_<NAME>_remote_exception_h h);
+
+/**
+ * @brief Destroys the <PREFIX> <NAME> remote exception handle.
+ *
+ * @param[in] h The <PREFIX> <NAME> remote exception handle
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int <PREFIX>_<NAME>_remote_exception_destroy(<PREFIX>_<NAME>_remote_exception_h h);
+)__c_cb";
+
+#endif // IDLC_C_GEN_C_STUB_HEADER_GENERATOR_CB_H_