Parse and expose ownership transfer for instance parameters

Knowing the ownership transfer for instance parameters is
necessary for correct memory management of functions which
"eat" their instance argument, such as g_dbus_method_invocation_return_*.
Parse this information from the gir file and store in the
typelib, and then provide new API on GICallableInfo to
retrieve this.

https://bugzilla.gnome.org/show_bug.cgi?id=729662
This commit is contained in:
Giovanni Campagna 2014-05-06 18:53:21 +02:00
parent d2514073b9
commit 9921571eb0
7 changed files with 108 additions and 6 deletions

View File

@ -275,6 +275,32 @@ g_callable_info_get_caller_owns (GICallableInfo *info)
return GI_TRANSFER_NOTHING;
}
/**
* g_callable_info_get_instance_ownership_transfer:
* @info: a #GICallableInfo
*
* Obtains the ownership transfer for the instance argument.
* #GITransfer contains a list of possible transfer values.
*
* Returns: the transfer
*/
GITransfer
g_callable_info_get_instance_ownership_transfer (GICallableInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo*) info;
SignatureBlob *blob;
g_return_val_if_fail (info != NULL, -1);
g_return_val_if_fail (GI_IS_CALLABLE_INFO (info), -1);
blob = (SignatureBlob *)&rinfo->typelib->data[signature_offset (info)];
if (blob->instance_transfer_ownership)
return GI_TRANSFER_EVERYTHING;
else
return GI_TRANSFER_NOTHING;
}
/**
* g_callable_info_get_n_args:
* @info: a #GICallableInfo

View File

@ -73,6 +73,8 @@ gboolean g_callable_info_invoke (GICallableInfo *info,
gboolean is_method,
gboolean throws,
GError **error);
GITransfer g_callable_info_get_instance_ownership_transfer (GICallableInfo *info);
G_END_DECLS

View File

@ -26,6 +26,7 @@ g_info_new
g_callable_info_can_throw_gerror
g_callable_info_get_arg
g_callable_info_get_caller_owns
g_callable_info_get_instance_ownership_transfer
g_callable_info_get_n_args
g_callable_info_get_return_attribute
g_callable_info_get_return_type

View File

@ -1664,6 +1664,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob2->caller_owns_return_value = function->result->transfer;
blob2->caller_owns_return_container = function->result->shallow_transfer;
blob2->skip_return = function->result->skip;
blob2->instance_transfer_ownership = function->instance_transfer_full;
blob2->reserved = 0;
blob2->n_arguments = n;
@ -1762,6 +1763,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob2->may_return_null = signal->result->nullable;
blob2->caller_owns_return_value = signal->result->transfer;
blob2->caller_owns_return_container = signal->result->shallow_transfer;
blob2->instance_transfer_ownership = signal->instance_transfer_full;
blob2->reserved = 0;
blob2->n_arguments = n;
@ -1820,6 +1822,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob2->may_return_null = vfunc->result->nullable;
blob2->caller_owns_return_value = vfunc->result->transfer;
blob2->caller_owns_return_container = vfunc->result->shallow_transfer;
blob2->instance_transfer_ownership = vfunc->instance_transfer_full;
blob2->reserved = 0;
blob2->n_arguments = n;

View File

@ -100,6 +100,7 @@ struct _GIrNodeFunction
gboolean is_constructor;
gboolean wraps_vfunc;
gboolean throws;
gboolean instance_transfer_full;
gchar *symbol;
@ -188,6 +189,7 @@ struct _GIrNodeSignal
gboolean detailed;
gboolean action;
gboolean no_hooks;
gboolean instance_transfer_full;
gboolean has_class_closure;
gboolean true_stops_emit;
@ -208,6 +210,7 @@ struct _GIrNodeVFunc
gboolean must_not_be_implemented;
gboolean is_class_closure;
gboolean throws;
gboolean instance_transfer_full;
char *invoker;

View File

@ -1046,6 +1046,71 @@ parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *n
return TRUE;
}
static gboolean
start_instance_parameter (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
ParseContext *ctx,
GError **error)
{
const gchar *transfer;
gboolean transfer_full;
if (!(strcmp (element_name, "instance-parameter") == 0 &&
ctx->state == STATE_FUNCTION_PARAMETERS))
return FALSE;
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
state_switch (ctx, STATE_PASSTHROUGH);
if (strcmp (transfer, "full") == 0)
transfer_full = TRUE;
else if (strcmp (transfer, "none") == 0)
transfer_full = FALSE;
else
{
g_set_error (error, G_MARKUP_ERROR,
G_MARKUP_ERROR_INVALID_CONTENT,
"invalid value for 'transfer-ownership' for instance parameter: %s", transfer);
return FALSE;
}
switch (CURRENT_NODE (ctx)->type)
{
case G_IR_NODE_FUNCTION:
case G_IR_NODE_CALLBACK:
{
GIrNodeFunction *func;
func = (GIrNodeFunction *)CURRENT_NODE (ctx);
func->instance_transfer_full = transfer_full;
}
break;
case G_IR_NODE_SIGNAL:
{
GIrNodeSignal *signal;
signal = (GIrNodeSignal *)CURRENT_NODE (ctx);
signal->instance_transfer_full = transfer_full;
}
break;
case G_IR_NODE_VFUNC:
{
GIrNodeVFunc *vfunc;
vfunc = (GIrNodeVFunc *)CURRENT_NODE (ctx);
vfunc->instance_transfer_full = transfer_full;
}
break;
default:
g_assert_not_reached ();
}
return TRUE;
}
static gboolean
start_parameter (GMarkupParseContext *context,
const gchar *element_name,
@ -2848,11 +2913,10 @@ start_element_handler (GMarkupParseContext *context,
attribute_names, attribute_values,
ctx, error))
goto out;
else if (strcmp (element_name, "instance-parameter") == 0)
{
state_switch (ctx, STATE_PASSTHROUGH);
goto out;
}
else if (start_instance_parameter (context, element_name,
attribute_names, attribute_values,
ctx, error))
goto out;
else if (strcmp (element_name, "c:include") == 0)
{
state_switch (ctx, STATE_C_INCLUDE);

View File

@ -465,6 +465,8 @@ typedef struct {
* freeing the container, but not its contents.
* @skip_return: Indicates that the return value is only useful in C and should
* be skipped.
* @instance_transfer_ownership: When calling, the function assumes ownership of
* the instance parameter.
* @reserved: Reserved for future use.
* @n_arguments: The number of arguments that this function expects, also the
* length of the array of ArgBlobs.
@ -479,7 +481,8 @@ typedef struct {
guint16 caller_owns_return_value : 1;
guint16 caller_owns_return_container : 1;
guint16 skip_return : 1;
guint16 reserved :12;
guint16 instance_transfer_ownership : 1;
guint16 reserved :11;
guint16 n_arguments;