diff options
-rw-r--r-- | girepository/gicallableinfo.c | 26 | ||||
-rw-r--r-- | girepository/gicallableinfo.h | 2 | ||||
-rw-r--r-- | girepository/girepository.symbols | 1 | ||||
-rw-r--r-- | girepository/girnode.c | 3 | ||||
-rw-r--r-- | girepository/girnode.h | 3 | ||||
-rw-r--r-- | girepository/girparser.c | 74 | ||||
-rw-r--r-- | girepository/gitypelib-internal.h | 5 | ||||
-rw-r--r-- | tests/repository/gitypelibtest.c | 29 | ||||
-rw-r--r-- | tests/scanner/Regress-1.0-C-expected/Regress.TestObj.instance_method_full.page | 38 | ||||
-rw-r--r-- | tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.instance_method_full.page | 26 | ||||
-rw-r--r-- | tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.instance_method_full.page | 37 | ||||
-rw-r--r-- | tests/scanner/Regress-1.0-expected.gir | 11 | ||||
-rw-r--r-- | tests/scanner/Regress-1.0-sections-expected.txt | 1 | ||||
-rw-r--r-- | tests/scanner/regress.c | 11 | ||||
-rw-r--r-- | tests/scanner/regress.h | 1 |
15 files changed, 262 insertions, 6 deletions
diff --git a/girepository/gicallableinfo.c b/girepository/gicallableinfo.c index e69e3e9d..702e16cd 100644 --- a/girepository/gicallableinfo.c +++ b/girepository/gicallableinfo.c @@ -276,6 +276,32 @@ g_callable_info_get_caller_owns (GICallableInfo *info) } /** + * 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 * diff --git a/girepository/gicallableinfo.h b/girepository/gicallableinfo.h index 71f9d0c6..f273d290 100644 --- a/girepository/gicallableinfo.h +++ b/girepository/gicallableinfo.h @@ -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 diff --git a/girepository/girepository.symbols b/girepository/girepository.symbols index 5f01adff..48fb0d90 100644 --- a/girepository/girepository.symbols +++ b/girepository/girepository.symbols @@ -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 diff --git a/girepository/girnode.c b/girepository/girnode.c index 53385c26..a7a77e31 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -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; diff --git a/girepository/girnode.h b/girepository/girnode.h index 4beef7f8..02196e7f 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -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; diff --git a/girepository/girparser.c b/girepository/girparser.c index 6c768669..f928c2e2 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -1047,6 +1047,71 @@ parse_param_transfer (GIrNodeParam *param, const gchar *transfer, const gchar *n } 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, const gchar **attribute_names, @@ -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); diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index 93d621b2..5ccb6173 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -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; diff --git a/tests/repository/gitypelibtest.c b/tests/repository/gitypelibtest.c index 565c95c3..7b9cb357 100644 --- a/tests/repository/gitypelibtest.c +++ b/tests/repository/gitypelibtest.c @@ -276,6 +276,34 @@ test_signal_array_len (GIRepository * repo) g_base_info_unref (testobj_info); } +static void +test_instance_transfer_ownership (GIRepository * repo) +{ + GIObjectInfo *testobj_info; + GIFunctionInfo *func_info; + GITransfer transfer; + + g_assert (g_irepository_require (repo, "Regress", NULL, 0, NULL)); + testobj_info = g_irepository_find_by_name (repo, "Regress", "TestObj"); + g_assert (testobj_info != NULL); + + func_info = g_object_info_find_method (testobj_info, "instance_method"); + g_assert (func_info != NULL); + transfer = g_callable_info_get_instance_ownership_transfer ((GICallableInfo*) func_info); + g_assert_cmpint (GI_TRANSFER_NOTHING, ==, transfer); + + g_base_info_unref (func_info); + + func_info = g_object_info_find_method (testobj_info, "instance_method_full"); + g_assert (func_info != NULL); + transfer = g_callable_info_get_instance_ownership_transfer ((GICallableInfo*) func_info); + g_assert_cmpint (GI_TRANSFER_EVERYTHING, ==, transfer); + + g_base_info_unref (func_info); + + g_base_info_unref (testobj_info); +} + int main (int argc, char **argv) { @@ -292,6 +320,7 @@ main (int argc, char **argv) test_hash_with_cairo_typelib (repo); test_char_types (repo); test_signal_array_len (repo); + test_instance_transfer_ownership (repo); exit (0); } diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestObj.instance_method_full.page b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj.instance_method_full.page new file mode 100644 index 00000000..2222becb --- /dev/null +++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj.instance_method_full.page @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<page id="Regress.TestObj.instance_method_full" + type="topic" + style="method" + xmlns="http://projectmallard.org/1.0/" + xmlns:api="http://projectmallard.org/experimental/api/" + xmlns:ui="http://projectmallard.org/1.0/ui/"> + <info> + <link xref="Regress.TestObj" group="method" type="guide"/> + <api:function> + <api:returns> + <api:type>void</api:type> + </api:returns> + <api:name>regress_test_obj_instance_method_full</api:name> + <api:arg> + <api:type>RegressTestObj*</api:type> + <api:name>obj</api:name> + </api:arg> + </api:function> + </info> + <title>regress_test_obj_instance_method_full</title> + <synopsis><code mime="text/x-csrc"> +void regress_test_obj_instance_method_full (RegressTestObj* obj); + </code></synopsis> + + +<terms> +<item> +<title><code>obj</code></title> + +</item> +<item> +<title><code>Returns</code></title> + +</item> +</terms> + +</page> diff --git a/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.instance_method_full.page b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.instance_method_full.page new file mode 100644 index 00000000..5b7e1c93 --- /dev/null +++ b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.instance_method_full.page @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<page id="Regress.TestObj.instance_method_full" + type="topic" + style="method" + xmlns="http://projectmallard.org/1.0/" + xmlns:api="http://projectmallard.org/experimental/api/" + xmlns:ui="http://projectmallard.org/1.0/ui/"> + <info> + <link xref="Regress.TestObj" group="method" type="guide"/> + <api:function> + <api:returns> + <api:type>void</api:type> + </api:returns> + <api:name>regress_test_obj_instance_method_full</api:name> + </api:function> + </info> + <title>Regress.TestObj.prototype.instance_method_full</title> + <synopsis><code mime="text/x-gjs"> +function instance_method_full(): void { + // Gjs wrapper for regress_test_obj_instance_method_full() +} + </code></synopsis> + + + +</page> diff --git a/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.instance_method_full.page b/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.instance_method_full.page new file mode 100644 index 00000000..2b5c1dcf --- /dev/null +++ b/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.instance_method_full.page @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<page id="Regress.TestObj.instance_method_full" + type="topic" + style="method" + xmlns="http://projectmallard.org/1.0/" + xmlns:api="http://projectmallard.org/experimental/api/" + xmlns:ui="http://projectmallard.org/1.0/ui/"> + <info> + <link xref="Regress.TestObj" group="method" type="guide"/> + <api:function> + <api:returns> + <api:type>none</api:type> + </api:returns> + <api:name>regress_test_obj_instance_method_full</api:name> + <api:arg> + <api:type>Regress.TestObj</api:type> + <api:name>self</api:name> + </api:arg> + </api:function> + </info> + <title>Regress.TestObj.instance_method_full</title> + <synopsis><code mime="text/x-python"> +@accepts(Regress.TestObj) +@returns(none) +def instance_method_full(self): + # Python wrapper for regress_test_obj_instance_method_full() + </code></synopsis> + + +<terms> +<item> +<title><code>self</code></title> + +</item> +</terms> + +</page> diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir index 1c9c300f..89ecaa45 100644 --- a/tests/scanner/Regress-1.0-expected.gir +++ b/tests/scanner/Regress-1.0-expected.gir @@ -3057,6 +3057,17 @@ case.</doc> </parameter> </parameters> </method> + <method name="instance_method_full" + c:identifier="regress_test_obj_instance_method_full"> + <return-value transfer-ownership="none"> + <type name="none" c:type="void"/> + </return-value> + <parameters> + <instance-parameter name="obj" transfer-ownership="full"> + <type name="TestObj" c:type="RegressTestObj*"/> + </instance-parameter> + </parameters> + </method> <method name="set_bare" c:identifier="regress_test_obj_set_bare"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> diff --git a/tests/scanner/Regress-1.0-sections-expected.txt b/tests/scanner/Regress-1.0-sections-expected.txt index c9ff60a3..187aa16d 100644 --- a/tests/scanner/Regress-1.0-sections-expected.txt +++ b/tests/scanner/Regress-1.0-sections-expected.txt @@ -334,6 +334,7 @@ regress_test_obj_emit_sig_with_uint64 regress_forced_method regress_test_obj_instance_method regress_test_obj_instance_method_callback +regress_test_obj_instance_method_full regress_test_obj_set_bare regress_test_obj_skip_inout_param regress_test_obj_skip_out_param diff --git a/tests/scanner/regress.c b/tests/scanner/regress.c index 1bad36e3..b42e0cd0 100644 --- a/tests/scanner/regress.c +++ b/tests/scanner/regress.c @@ -2679,6 +2679,17 @@ regress_test_obj_instance_method (RegressTestObj *obj) return -1; } +/** + * regress_test_obj_instance_method_full: + * @obj: (transfer full): + * + */ +void +regress_test_obj_instance_method_full (RegressTestObj *obj) +{ + g_object_unref (obj); +} + double regress_test_obj_static_method (int x) { diff --git a/tests/scanner/regress.h b/tests/scanner/regress.h index e2e645ba..667f1298 100644 --- a/tests/scanner/regress.h +++ b/tests/scanner/regress.h @@ -527,6 +527,7 @@ void regress_test_obj_emit_sig_with_foreign_struct (RegressTestObj *obj); void regress_test_obj_emit_sig_with_int64 (RegressTestObj *obj); void regress_test_obj_emit_sig_with_uint64 (RegressTestObj *obj); int regress_test_obj_instance_method (RegressTestObj *obj); +void regress_test_obj_instance_method_full (RegressTestObj *obj); double regress_test_obj_static_method (int x); void regress_forced_method (RegressTestObj *obj); |