/
githubmirror
/
libxmlb
Обзор
Документация
Войти
/
githubmirror
/
libxmlb
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
0.3.2
src/xb-value-bindings.c
312 строк
8 KB
Richard Hughes
trivial: Fix the GObject-Introspection of xb_value_bindings_lookup_opcode()
11 май 2021, 11:12
11 май 2021, 11:12
0e4a1a3
Код
Авторство
О чём код?
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * vi:set noexpandtab tabstop=8 shiftwidth=8: * * Copyright (C) 2020 Endless OS Foundation LLC * * Author: Philip Withnall <withnall@endlessm.com> * * SPDX-License-Identifier: LGPL-2.1+ */ #define G_LOG_DOMAIN "XbValueBindings" #include "config.h" #include <glib.h> #include "xb-opcode-private.h" #include "xb-value-bindings.h" typedef struct { enum { KIND_NONE, KIND_TEXT, KIND_INTEGER, } kind; union { gchar *text; guint32 integer; }; GDestroyNotify destroy_func; } BoundValue; typedef struct { /* Currently limited to 4 values since that’s all that any client * uses. This could be expanded to dynamically allow more in future. */ BoundValue values[4]; gpointer dummy[3]; } RealValueBindings; G_STATIC_ASSERT (sizeof (XbValueBindings) == sizeof (RealValueBindings)); #if GLIB_CHECK_VERSION(2, 60, 0) G_STATIC_ASSERT (G_ALIGNOF (XbValueBindings) == G_ALIGNOF (RealValueBindings)); #endif G_DEFINE_BOXED_TYPE (XbValueBindings, xb_value_bindings, xb_value_bindings_copy, xb_value_bindings_free) /** * xb_value_bindings_init: * @self: an uninitialised #XbValueBindings to initialise * * Initialise a stack-allocated #XbValueBindings struct so it can be used. * * Stack-allocated #XbValueBindings instances should be freed once finished * with, using xb_value_bindings_clear() (or `g_auto(XbValueBindings)`, which is * equivalent). * * Since: 0.3.0 */ void xb_value_bindings_init (XbValueBindings *self) { RealValueBindings *_self = (RealValueBindings *) self; for (gsize i = 0; i < G_N_ELEMENTS (_self->values); i++) _self->values[i].kind = KIND_NONE; } static void xb_value_bindings_clear_index (XbValueBindings *self, guint idx) { RealValueBindings *_self = (RealValueBindings *) self; g_return_if_fail (idx < G_N_ELEMENTS (_self->values)); if (_self->values[idx].kind == KIND_TEXT && _self->values[idx].destroy_func) _self->values[idx].destroy_func (_self->values[idx].text); _self->values[idx].kind = KIND_NONE; _self->values[idx].text = NULL; _self->values[idx].destroy_func = NULL; } /** * xb_value_bindings_clear: * @self: an #XbValueBindings * * Clear an #XbValueBindings, freeing any allocated memory it points to. * * After this function has been called, the contents of the #XbValueBindings are * undefined, and it’s only safe to call xb_value_bindings_init() on it. * * Since: 0.3.0 */ void xb_value_bindings_clear (XbValueBindings *self) { RealValueBindings *_self = (RealValueBindings *) self; for (gsize i = 0; i < G_N_ELEMENTS (_self->values); i++) xb_value_bindings_clear_index (self, i); } /** * xb_value_bindings_copy: * @self: an #XbValueBindings * * Copy @self into a new heap-allocated #XbValueBindings instance. * * Returns: (transfer full): a copy of @self * Since: 0.3.0 */ XbValueBindings * xb_value_bindings_copy (XbValueBindings *self) { RealValueBindings *_self = (RealValueBindings *) self; g_autoptr(XbValueBindings) copy = g_new0 (XbValueBindings, 1); xb_value_bindings_init (copy); for (gsize i = 0; i < G_N_ELEMENTS (_self->values); i++) { gboolean copied = xb_value_bindings_copy_binding (self, i, copy, i); g_assert (copied); } return g_steal_pointer (©); } /** * xb_value_bindings_free: * @self: a heap-allocated #XbValueBindings * * Free a heap-allocated #XbValueBindings instance. This should be used on * #XbValueBindings instances created with xb_value_bindings_copy(). * * For stack-allocated instances, xb_value_bindings_clear() should be used * instead. * * Since: 0.3.0 */ void xb_value_bindings_free (XbValueBindings *self) { g_return_if_fail (self != NULL); xb_value_bindings_clear (self); g_free (self); } /** * xb_value_bindings_is_bound: * @self: an #XbValueBindings * @idx: 0-based index of the binding to check * * Check whether a value has been bound to the given index using (for example) * xb_value_bindings_bind_str(). * * Returns: %TRUE if a value is bound to @idx, %FALSE otherwise * Since: 0.3.0 */ gboolean xb_value_bindings_is_bound (XbValueBindings *self, guint idx) { RealValueBindings *_self = (RealValueBindings *) self; return (idx < G_N_ELEMENTS (_self->values) && _self->values[idx].kind != KIND_NONE); } /** * xb_value_bindings_bind_str: * @self: an #XbValueBindings * @idx: 0-based index to bind to * @str: (transfer full) (not nullable): a string to bind to @idx * @destroy_func: (nullable): function to free @str * * Bind @str to @idx in the value bindings. * * This will overwrite any previous binding at @idx. It will take ownership of * @str, and an appropriate @destroy_func must be provided to free @str once the * binding is no longer needed. @destroy_func will be called exactly once at * some point before the #XbValueBindings is cleared or freed. * * Since: 0.3.0 */ void xb_value_bindings_bind_str (XbValueBindings *self, guint idx, const gchar *str, GDestroyNotify destroy_func) { RealValueBindings *_self = (RealValueBindings *) self; g_return_if_fail (self != NULL); g_return_if_fail (str != NULL); /* Currently limited to two values, but this restriction could be lifted * in future. */ g_return_if_fail (idx < G_N_ELEMENTS (_self->values)); xb_value_bindings_clear_index (self, idx); _self->values[idx].kind = KIND_TEXT; _self->values[idx].text = (gchar *) str; _self->values[idx].destroy_func = destroy_func; } /** * xb_value_bindings_bind_val: * @self: an #XbValueBindings * @idx: 0-based index to bind to * @val: an integer to bind to @idx * * Bind @val to @idx in the value bindings. * * This will overwrite any previous binding at @idx. * * Since: 0.3.0 */ void xb_value_bindings_bind_val (XbValueBindings *self, guint idx, guint32 val) { RealValueBindings *_self = (RealValueBindings *) self; g_return_if_fail (self != NULL); /* Currently limited to two values, but this restriction could be lifted * in future. */ g_return_if_fail (idx < G_N_ELEMENTS (_self->values)); xb_value_bindings_clear_index (self, idx); _self->values[idx].kind = KIND_INTEGER; _self->values[idx].integer = val; _self->values[idx].destroy_func = NULL; } /** * xb_value_bindings_lookup_opcode: * @self: an #XbValueBindings * @idx: 0-based index to look up the binding from * @opcode_out: (out caller-allocates) (not nullable): pointer to an #XbOpcode * to initialise from the binding * * Initialises an #XbOpcode with the value bound to @idx, if a value is bound. * If no value is bound, @opcode_out is not touched and %FALSE is returned. * * @opcode_out is initialised to point to the data inside the #XbValueBindings, * so must have a shorter lifetime than the #XbValueBindings. It will be of kind * %XB_OPCODE_KIND_BOUND_TEXT or %XB_OPCODE_KIND_BOUND_INTEGER. * * Returns: %TRUE if @idx was bound, %FALSE otherwise * Since: 0.3.0 */ gboolean xb_value_bindings_lookup_opcode (XbValueBindings *self, guint idx, XbOpcode *opcode_out) { RealValueBindings *_self = (RealValueBindings *) self; if (!xb_value_bindings_is_bound (self, idx)) return FALSE; switch (_self->values[idx].kind) { case KIND_TEXT: xb_opcode_init (opcode_out, XB_OPCODE_KIND_BOUND_TEXT, _self->values[idx].text, 0, NULL); break; case KIND_INTEGER: xb_opcode_init (opcode_out, XB_OPCODE_KIND_BOUND_INTEGER, NULL, _self->values[idx].integer, NULL); break; case KIND_NONE: default: g_assert_not_reached (); } return TRUE; } /** * xb_value_bindings_copy_binding: * @self: an #XbValueBindings to copy from * @idx: 0-based index to look up the binding from in @self * @dest: an #XbValueBindings to copy to * @dest_idx: 0-based index to copy the binding to in @dest * * Copies the value bound at @idx on @self to @dest_idx on @dest. If no value is * bound at @idx, @dest is not modified and %FALSE is returned. * * @dest must be initialised. If a binding already exists at @dest_idx, it will * be overwritten. * * Returns: %TRUE if @idx was bound, %FALSE otherwise * Since: 0.3.0 */ gboolean xb_value_bindings_copy_binding (XbValueBindings *self, guint idx, XbValueBindings *dest, guint dest_idx) { RealValueBindings *_self = (RealValueBindings *) self; if (!xb_value_bindings_is_bound (self, idx)) return FALSE; switch (_self->values[idx].kind) { case KIND_TEXT: xb_value_bindings_bind_str (dest, dest_idx, _self->values[idx].text, NULL); break; case KIND_INTEGER: xb_value_bindings_bind_val (dest, dest_idx, _self->values[idx].integer); break; case KIND_NONE: default: g_assert_not_reached (); } return TRUE; }