mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-31 22:23:39 +02:00
Support the (transfer) annotation for properties.
* girepository/*: Add g_property_info_get_ownership_transfer() and write the transfer attribute of properties into the typelib. * giscanner/*: Parse the (transfer) annotation and write it into the .gir. * tools/generate.c: Read the transfer annotation for properties and write to the .tgir. https://bugzilla.gnome.org/show_bug.cgi?id=620484
This commit is contained in:
@@ -57,3 +57,30 @@ g_property_info_get_type (GIPropertyInfo *info)
|
|||||||
return _g_type_info_new ((GIBaseInfo*)info, rinfo->typelib, rinfo->offset + G_STRUCT_OFFSET (PropertyBlob, type));
|
return _g_type_info_new ((GIBaseInfo*)info, rinfo->typelib, rinfo->offset + G_STRUCT_OFFSET (PropertyBlob, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_property_info_get_ownership_transfer:
|
||||||
|
* @info: a #GIPropertyInfo
|
||||||
|
*
|
||||||
|
* Obtain the ownership transfer for this property. See #GITransfer for more
|
||||||
|
* information about transfer values.
|
||||||
|
*
|
||||||
|
* Returns: the transfer
|
||||||
|
*/
|
||||||
|
GITransfer
|
||||||
|
g_property_info_get_ownership_transfer (GIPropertyInfo *info)
|
||||||
|
{
|
||||||
|
GIRealInfo *rinfo = (GIRealInfo *)info;
|
||||||
|
PropertyBlob *blob;
|
||||||
|
|
||||||
|
g_return_val_if_fail (info != NULL, -1);
|
||||||
|
g_return_val_if_fail (GI_IS_PROPERTY_INFO (info), -1);
|
||||||
|
|
||||||
|
blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
|
||||||
|
|
||||||
|
if (blob->transfer_ownership)
|
||||||
|
return GI_TRANSFER_EVERYTHING;
|
||||||
|
else if (blob->transfer_container_ownership)
|
||||||
|
return GI_TRANSFER_CONTAINER;
|
||||||
|
else
|
||||||
|
return GI_TRANSFER_NOTHING;
|
||||||
|
}
|
||||||
|
@@ -35,6 +35,7 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
GParamFlags g_property_info_get_flags (GIPropertyInfo *info);
|
GParamFlags g_property_info_get_flags (GIPropertyInfo *info);
|
||||||
GITypeInfo * g_property_info_get_type (GIPropertyInfo *info);
|
GITypeInfo * g_property_info_get_type (GIPropertyInfo *info);
|
||||||
|
GITransfer g_property_info_get_ownership_transfer (GIPropertyInfo *info);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -1648,6 +1648,8 @@ g_ir_node_build_typelib (GIrNode *node,
|
|||||||
blob->writable = prop->writable;
|
blob->writable = prop->writable;
|
||||||
blob->construct = prop->construct;
|
blob->construct = prop->construct;
|
||||||
blob->construct_only = prop->construct_only;
|
blob->construct_only = prop->construct_only;
|
||||||
|
blob->transfer_ownership = prop->transfer;
|
||||||
|
blob->transfer_container_ownership = prop->shallow_transfer;
|
||||||
blob->reserved = 0;
|
blob->reserved = 0;
|
||||||
|
|
||||||
g_ir_node_build_typelib ((GIrNode *)prop->type,
|
g_ir_node_build_typelib ((GIrNode *)prop->type,
|
||||||
|
@@ -178,6 +178,8 @@ struct _GIrNodeProperty
|
|||||||
gboolean writable;
|
gboolean writable;
|
||||||
gboolean construct;
|
gboolean construct;
|
||||||
gboolean construct_only;
|
gboolean construct_only;
|
||||||
|
gboolean transfer;
|
||||||
|
gboolean shallow_transfer;
|
||||||
|
|
||||||
GIrNodeType *type;
|
GIrNodeType *type;
|
||||||
};
|
};
|
||||||
|
42
girparser.c
42
girparser.c
@@ -840,6 +840,44 @@ start_function (GMarkupParseContext *context,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_property_transfer (GIrNodeProperty *property,
|
||||||
|
const gchar *transfer,
|
||||||
|
ParseContext *ctx)
|
||||||
|
{
|
||||||
|
if (transfer == NULL)
|
||||||
|
{
|
||||||
|
GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
||||||
|
|
||||||
|
g_warning ("required attribute 'transfer-ownership' for property '%s' in "
|
||||||
|
"type '%s.%s'", property->node.name, ctx->namespace,
|
||||||
|
iface->node.name);
|
||||||
|
}
|
||||||
|
else if (strcmp (transfer, "none") == 0)
|
||||||
|
{
|
||||||
|
property->transfer = FALSE;
|
||||||
|
property->shallow_transfer = FALSE;
|
||||||
|
}
|
||||||
|
else if (strcmp (transfer, "container") == 0)
|
||||||
|
{
|
||||||
|
property->transfer = FALSE;
|
||||||
|
property->shallow_transfer = TRUE;
|
||||||
|
}
|
||||||
|
else if (strcmp (transfer, "full") == 0)
|
||||||
|
{
|
||||||
|
property->transfer = TRUE;
|
||||||
|
property->shallow_transfer = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GIrNodeInterface *iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
||||||
|
|
||||||
|
g_warning ("Unknown transfer-ownership value: '%s' for property '%s' in "
|
||||||
|
"type '%s.%s'", transfer, property->node.name, ctx->namespace,
|
||||||
|
iface->node.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name)
|
parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *name)
|
||||||
{
|
{
|
||||||
@@ -1237,12 +1275,14 @@ start_property (GMarkupParseContext *context,
|
|||||||
const gchar *writable;
|
const gchar *writable;
|
||||||
const gchar *construct;
|
const gchar *construct;
|
||||||
const gchar *construct_only;
|
const gchar *construct_only;
|
||||||
|
const gchar *transfer;
|
||||||
|
|
||||||
name = find_attribute ("name", attribute_names, attribute_values);
|
name = find_attribute ("name", attribute_names, attribute_values);
|
||||||
readable = find_attribute ("readable", attribute_names, attribute_values);
|
readable = find_attribute ("readable", attribute_names, attribute_values);
|
||||||
writable = find_attribute ("writable", attribute_names, attribute_values);
|
writable = find_attribute ("writable", attribute_names, attribute_values);
|
||||||
construct = find_attribute ("construct", attribute_names, attribute_values);
|
construct = find_attribute ("construct", attribute_names, attribute_values);
|
||||||
construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
|
construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
|
||||||
|
transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
|
||||||
|
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
MISSING_ATTRIBUTE (context, error, element_name, "name");
|
||||||
@@ -1274,6 +1314,8 @@ start_property (GMarkupParseContext *context,
|
|||||||
else
|
else
|
||||||
property->construct_only = FALSE;
|
property->construct_only = FALSE;
|
||||||
|
|
||||||
|
parse_property_transfer (property, transfer, ctx);
|
||||||
|
|
||||||
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
iface = (GIrNodeInterface *)CURRENT_NODE (ctx);
|
||||||
iface->members = g_list_append (iface->members, property);
|
iface->members = g_list_append (iface->members, property);
|
||||||
|
|
||||||
|
52
girwriter.c
52
girwriter.c
@@ -187,6 +187,26 @@ write_type_name_attribute (const gchar *namespace,
|
|||||||
xml_printf (file, "\"");
|
xml_printf (file, "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_ownership_transfer (GITransfer transfer,
|
||||||
|
Xml *file)
|
||||||
|
{
|
||||||
|
switch (transfer)
|
||||||
|
{
|
||||||
|
case GI_TRANSFER_NOTHING:
|
||||||
|
xml_printf (file, " transfer-ownership=\"none\"");
|
||||||
|
break;
|
||||||
|
case GI_TRANSFER_CONTAINER:
|
||||||
|
xml_printf (file, " transfer-ownership=\"container\"");
|
||||||
|
break;
|
||||||
|
case GI_TRANSFER_EVERYTHING:
|
||||||
|
xml_printf (file, " transfer-ownership=\"full\"");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_type_info (const gchar *namespace,
|
write_type_info (const gchar *namespace,
|
||||||
GITypeInfo *info,
|
GITypeInfo *info,
|
||||||
@@ -443,20 +463,7 @@ write_callable_info (const gchar *namespace,
|
|||||||
|
|
||||||
xml_start_element (file, "return-value");
|
xml_start_element (file, "return-value");
|
||||||
|
|
||||||
switch (g_callable_info_get_caller_owns (info))
|
write_ownership_transfer (g_callable_info_get_caller_owns (info), file);
|
||||||
{
|
|
||||||
case GI_TRANSFER_NOTHING:
|
|
||||||
xml_printf (file, " transfer-ownership=\"none\"");
|
|
||||||
break;
|
|
||||||
case GI_TRANSFER_CONTAINER:
|
|
||||||
xml_printf (file, " transfer-ownership=\"container\"");
|
|
||||||
break;
|
|
||||||
case GI_TRANSFER_EVERYTHING:
|
|
||||||
xml_printf (file, " transfer-ownership=\"full\"");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_callable_info_may_return_null (info))
|
if (g_callable_info_may_return_null (info))
|
||||||
xml_printf (file, " allow-none=\"1\"");
|
xml_printf (file, " allow-none=\"1\"");
|
||||||
@@ -477,20 +484,7 @@ write_callable_info (const gchar *namespace,
|
|||||||
xml_printf (file, " name=\"%s\"",
|
xml_printf (file, " name=\"%s\"",
|
||||||
g_base_info_get_name ((GIBaseInfo *) arg));
|
g_base_info_get_name ((GIBaseInfo *) arg));
|
||||||
|
|
||||||
switch (g_arg_info_get_ownership_transfer (arg))
|
write_ownership_transfer (g_arg_info_get_ownership_transfer (arg), file);
|
||||||
{
|
|
||||||
case GI_TRANSFER_NOTHING:
|
|
||||||
xml_printf (file, " transfer-ownership=\"none\"");
|
|
||||||
break;
|
|
||||||
case GI_TRANSFER_CONTAINER:
|
|
||||||
xml_printf (file, " transfer-ownership=\"container\"");
|
|
||||||
break;
|
|
||||||
case GI_TRANSFER_EVERYTHING:
|
|
||||||
xml_printf (file, " transfer-ownership=\"full\"");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (g_arg_info_get_direction (arg))
|
switch (g_arg_info_get_direction (arg))
|
||||||
{
|
{
|
||||||
@@ -968,6 +962,8 @@ write_property_info (const gchar *namespace,
|
|||||||
if (flags & G_PARAM_CONSTRUCT_ONLY)
|
if (flags & G_PARAM_CONSTRUCT_ONLY)
|
||||||
xml_printf (file, " construct-only=\"1\"");
|
xml_printf (file, " construct-only=\"1\"");
|
||||||
|
|
||||||
|
write_ownership_transfer (g_property_info_get_ownership_transfer (info), file);
|
||||||
|
|
||||||
write_attributes (file, (GIBaseInfo*) info);
|
write_attributes (file, (GIBaseInfo*) info);
|
||||||
|
|
||||||
type = g_property_info_get_type (info);
|
type = g_property_info_get_type (info);
|
||||||
|
@@ -815,17 +815,25 @@ typedef struct {
|
|||||||
* @writable:
|
* @writable:
|
||||||
* @construct:
|
* @construct:
|
||||||
* @construct_only: The ParamFlags used when registering the property.
|
* @construct_only: The ParamFlags used when registering the property.
|
||||||
|
* @transfer_ownership: When writing, the type containing the property takes
|
||||||
|
* ownership of the value. When reading, the returned value needs to be released
|
||||||
|
* by the caller.
|
||||||
|
* @transfer_container_ownership: For container types indicates that the
|
||||||
|
* ownership of the container, but not of its contents, is transferred. This is
|
||||||
|
* typically the case when reading lists of statically allocated things.
|
||||||
* @type: Describes the type of the property.
|
* @type: Describes the type of the property.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
guint32 name;
|
guint32 name;
|
||||||
|
|
||||||
guint32 deprecated : 1;
|
guint32 deprecated : 1;
|
||||||
guint32 readable : 1;
|
guint32 readable : 1;
|
||||||
guint32 writable : 1;
|
guint32 writable : 1;
|
||||||
guint32 construct : 1;
|
guint32 construct : 1;
|
||||||
guint32 construct_only : 1;
|
guint32 construct_only : 1;
|
||||||
guint32 reserved :27;
|
guint32 transfer_ownership : 1;
|
||||||
|
guint32 transfer_container_ownership : 1;
|
||||||
|
guint32 reserved :25;
|
||||||
|
|
||||||
guint32 reserved2;
|
guint32 reserved2;
|
||||||
|
|
||||||
|
28
gitypes.h
28
gitypes.h
@@ -241,13 +241,29 @@ typedef enum
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GITransfer:
|
* GITransfer:
|
||||||
* @GI_TRANSFER_NOTHING: transfer nothing to the caller
|
* @GI_TRANSFER_NOTHING: transfer nothing from the callee (function or the type
|
||||||
* @GI_TRANSFER_CONTAINER: transfer the container (eg list, array,
|
* instance the property belongs to) to the caller. The callee retains the
|
||||||
* hashtable), but no the contents to the caller.
|
* ownership of the transfer and the caller doesn't need to do anything to free
|
||||||
* @GI_TRANSFER_EVERYTHING: transfer everything to the caller.
|
* up the resources of this transfer.
|
||||||
|
* @GI_TRANSFER_CONTAINER: transfer the container (list, array, hash table) from
|
||||||
|
* the callee to the caller. The callee retains the ownership of the individual
|
||||||
|
* items in the container and the caller has to free up the container resources
|
||||||
|
* (g_list_free()/g_hash_table_destroy() etc) of this transfer.
|
||||||
|
* @GI_TRANSFER_EVERYTHING: transfer everything, eg the container and its
|
||||||
|
* contents from the callee to the caller. This is the case when the callee
|
||||||
|
* creates a copy of all the data it returns. The caller is responsible for
|
||||||
|
* cleaning up the container and item resources of this transfer.
|
||||||
*
|
*
|
||||||
* Represent the transfer ownership information of a #GICallableInfo or
|
* The transfer is the exchange of data between two parts, from the callee to
|
||||||
* a #GIArgInfo.
|
* the caller. The callee is either a function/method/signal or an
|
||||||
|
* object/interface where a property is defined. The caller is the side
|
||||||
|
* accessing a property or calling a function.
|
||||||
|
* #GITransfer specifies who's responsible for freeing the resources after the
|
||||||
|
* ownership transfer is complete. In case of a containing type such as a list,
|
||||||
|
* an array or a hash table the container itself is specified differently from
|
||||||
|
* the items within the container itself. Each container is freed differently,
|
||||||
|
* check the documentation for the types themselves for information on how to
|
||||||
|
* free them.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GI_TRANSFER_NOTHING,
|
GI_TRANSFER_NOTHING,
|
||||||
|
Reference in New Issue
Block a user