mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-07 17:54:05 +02:00
added newly added gobject/ headers.
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org> * glib-object.h: added newly added gobject/ headers. * gmesage.c: print g_message() output to stderr instead of stdout. Wed Oct 25 20:27:02 2000 Tim Janik <timj@gtk.org> * gtype.c (g_type_free_instance): for the moment, freeing object structures will fill their memory portion with 0xAA. there's a FIXME there, remove this line at a later point. Tue Oct 24 23:10:26 2000 Tim Janik <timj@gtk.org> * glib-genmarshal.1: * glib-genmarshal.c: added publically installed marshaller generator. * gtype.h: added G_TYPE_INSTANCE_GET_INTERFACE() to retrive a certain interface VTable from instances. Mon Oct 23 08:28:15 2000 Tim Janik <timj@gtk.org> * gobject.[hc]: new functions for closure maintenance: (g_object_watch_closure): maintain validity of the object and the closure for objects that are used as data part of a closure. (g_cclosure_new_object): convenience function to create C closures that have an object as data argument. (g_closure_new_object): convenience function to create closures that have an object as data argument. * gclosure.[hc]: implementation of GClosure mechanism. a closure is basically an encapsulation of a callback function and its environment. ideally, most places supporting callback functions will simply take a GClosure* pointer and thus unify callback environments wrg destroy notification etc. GClosure provides destroy notifiers for arbitrary data pointers, reference counting, invalidation notification (it can be invalidated which is merely a deactivate state) and a marshallinbg abstraction. GCClosure is also provided in these files, they present a specialized GClosure implementation for C language callbacks. * genum.c: macro cleanups. * gboxed.[hc]: new files, for boxed type abstraction. (g_boxed_copy): copy a boxed structure (g_boxed_free): free a boxed structure (g_value_set_boxed): (g_value_get_boxed): standard GValue functions for boxed types (g_boxed_type_register_static): convenience function for easy introduction of new G_TYPE_BOXED derivatives. * gparam.[hc]: introduced g_param_type_register_static(), a short hand for creation of new GParamSpec derived types. * gtype.[hc]: many fixes, introduced ability to flag individual type nodes as ABSTRACT upon registration, added value_peek_pointer() to the value table to peek at GValue contents as a pointer for types that support this. fixed up GValue checks. * gvalue.[hc]: added g_value_fits_pointer() and g_value_get_as_pointer() to peek at the value contents as pointer. * *.[hc]: adaptions to type macro fixes and changes in the type registration API. * many const corrections over the place. Sat Oct 21 02:49:56 2000 Tim Janik <timj@gtk.org> * gtype.c (g_type_conforms_to): this function basically behaves like and is_a check, except that it _additionally_ features interfaces for instantiatable types. enforce this in the second branch as well (`type' conforms_to `type') even if `type' is not an interface type. Fri Oct 20 15:31:04 2000 Tim Janik <timj@gtk.org> * gvaluetypes.[hc]: added G_TYPE_POINTER implementation from jrb. * gtype.[hc]: * gobject.c: * gvaluetypes.c: added GTypeValueTable.value_peek_pointer and suitable implementations of this for G_TYPE_STRING, G_TYPE_OBJECT and G_TYPE_POINTER. Mon Aug 21 04:13:37 2000 Tim Janik <timj@gtk.org> * gbsearcharray.[hc]: long standing needed generic implementation of a binary searchable, sorted and dynamically sized array.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,3 +1,9 @@
|
||||
Tue Oct 24 22:09:14 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-object.h: added newly added gobject/ headers.
|
||||
|
||||
* gmesage.c: print g_message() output to stderr instead of stdout.
|
||||
|
||||
2000-10-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
|
||||
|
||||
* configure.in: Use one = instead of two, which is plainly wrong.
|
||||
|
@@ -1,9 +1,45 @@
|
||||
<!-- ##### MACRO popen ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO pclose ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO lseek ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO getpid ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO close ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO fdopen ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO getcwd ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### USER_FUNCTION GSearchFunc ##### -->
|
||||
<para>
|
||||
Specifies the type of function passed to g_tree_search().
|
||||
@@ -15,31 +51,13 @@ Specifies the type of function passed to g_tree_search().
|
||||
desired key comes before @key in the sort order of the #GTree, or a positive
|
||||
value if the desired key comes after @key.
|
||||
|
||||
<!-- ##### FUNCTION g_node_insert_after ##### -->
|
||||
<para>
|
||||
Inserts a #GNode beneath the parent after the given sibling.
|
||||
</para>
|
||||
|
||||
@parent: the #GNode to place @node under.
|
||||
@sibling: the sibling #GNode to place @node after. If sibling is NULL,
|
||||
the node is inserted as the first child of @parent.
|
||||
@node: the #GNode to insert.
|
||||
@Returns: the inserted #GNode.
|
||||
|
||||
<!-- ##### FUNCTION g_convert_error_quark ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@Returns:
|
||||
|
||||
<!-- ##### MACRO write ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO pclose ##### -->
|
||||
<!-- ##### MACRO access ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
@@ -52,17 +70,18 @@ Turns the argument into a string literal by using the '#' stringizing operator.
|
||||
|
||||
@x: text to convert to a literal string.
|
||||
|
||||
<!-- ##### MACRO popen ##### -->
|
||||
<!-- ##### MACRO read ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO access ##### -->
|
||||
<!-- ##### FUNCTION g_convert_error_quark ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@Returns:
|
||||
|
||||
<!-- ##### MACRO open ##### -->
|
||||
<para>
|
||||
@@ -70,33 +89,3 @@ Turns the argument into a string literal by using the '#' stringizing operator.
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO getpid ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO fdopen ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO close ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO getcwd ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO read ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
@@ -39,6 +39,20 @@ only one statement is expected by the compiler.
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO G_BEGIN_DECLS ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO G_END_DECLS ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO G_N_ELEMENTS ##### -->
|
||||
<para>
|
||||
|
||||
@@ -52,6 +66,7 @@ only one statement is expected by the compiler.
|
||||
Portable way to copy <type>va_list</type> variables.
|
||||
</para>
|
||||
|
||||
<!-- # Unused Parameters # -->
|
||||
@ap1: the <type>va_list</type> variable to place a copy of @ap2 in.
|
||||
@ap2: a <type>va_list</type>.
|
||||
|
||||
@@ -101,6 +116,13 @@ It avoids possible compiler warnings. See the GNU C documentation for details.
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO G_GNUC_PURE ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO G_GNUC_PRINTF ##### -->
|
||||
<para>
|
||||
Expands to the GNU C format function attribute if the compiler is GNU C.
|
||||
|
@@ -98,6 +98,14 @@ If @mem is NULL it simply returns.
|
||||
@mem: the memory to free.
|
||||
|
||||
|
||||
<!-- ##### MACRO g_alloca ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@size:
|
||||
|
||||
|
||||
<!-- ##### MACRO g_memmove ##### -->
|
||||
<para>
|
||||
Copies a block of memory @n bytes long, from @s to @d.
|
||||
|
@@ -40,22 +40,107 @@ produce highly random lower bits too, but it is common not to rely on
|
||||
that, so choosing @a to be from 4 to 31 might be wise.
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### STRUCT GRand ##### -->
|
||||
<para>
|
||||
The #GRand struct is an opaque data structure. It should only be
|
||||
accessed through the g_rand_* functions.
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_new_with_seed ##### -->
|
||||
|
||||
|
||||
@seed:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_new ##### -->
|
||||
|
||||
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_free ##### -->
|
||||
|
||||
|
||||
@rand:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_set_seed ##### -->
|
||||
|
||||
|
||||
@rand:
|
||||
@seed:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_int ##### -->
|
||||
|
||||
|
||||
@rand:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_int_range ##### -->
|
||||
|
||||
|
||||
@rand:
|
||||
@min:
|
||||
@max:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_double ##### -->
|
||||
|
||||
|
||||
@rand:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_rand_double_range ##### -->
|
||||
|
||||
|
||||
@rand:
|
||||
@min:
|
||||
@max:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_random_set_seed ##### -->
|
||||
|
||||
|
||||
@seed:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_random_int ##### -->
|
||||
|
||||
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_random_int_range ##### -->
|
||||
|
||||
|
||||
@min:
|
||||
@max:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_random_double ##### -->
|
||||
|
||||
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_random_double_range ##### -->
|
||||
|
||||
|
||||
@min:
|
||||
@max:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
@@ -113,6 +113,18 @@ the node is inserted as the last child of @parent.
|
||||
@Returns: the inserted #GNode.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_node_insert_after ##### -->
|
||||
<para>
|
||||
Inserts a #GNode beneath the parent after the given sibling.
|
||||
</para>
|
||||
|
||||
@parent: the #GNode to place @node under.
|
||||
@sibling: the sibling #GNode to place @node after. If sibling is NULL,
|
||||
the node is inserted as the first child of @parent.
|
||||
@node: the #GNode to insert.
|
||||
@Returns: the inserted #GNode.
|
||||
|
||||
|
||||
<!-- ##### MACRO g_node_append ##### -->
|
||||
<para>
|
||||
Inserts a #GNode as the last child of the given parent.
|
||||
|
@@ -80,9 +80,9 @@ GType
|
||||
@G_TYPE_DOUBLE:
|
||||
@G_TYPE_STRING:
|
||||
@G_TYPE_PARAM:
|
||||
@G_TYPE_BOXED:
|
||||
@G_TYPE_POINTER:
|
||||
@G_TYPE_OBJECT:
|
||||
@G_TYPE_GTK_BOXED:
|
||||
@G_TYPE_GTK_POINTER:
|
||||
@G_TYPE_GTK_SIGNAL:
|
||||
@G_TYPE_BSE_PROCEDURE:
|
||||
@G_TYPE_BSE_TIME:
|
||||
@@ -213,6 +213,7 @@ GType
|
||||
@value_init:
|
||||
@value_free:
|
||||
@value_copy:
|
||||
@value_peek_pointer:
|
||||
@collect_type:
|
||||
@collect_value:
|
||||
@lcopy_type:
|
||||
@@ -571,10 +572,7 @@ GType
|
||||
|
||||
</para>
|
||||
|
||||
@G_TYPE_FLAG_CLASSED:
|
||||
@G_TYPE_FLAG_INSTANTIATABLE:
|
||||
@G_TYPE_FLAG_DERIVABLE:
|
||||
@G_TYPE_FLAG_DEEP_DERIVABLE:
|
||||
@G_TYPE_FLAG_ABSTRACT:
|
||||
|
||||
<!-- ##### FUNCTION g_type_register_static ##### -->
|
||||
<para>
|
||||
@@ -584,6 +582,7 @@ GType
|
||||
@parent_type:
|
||||
@type_name:
|
||||
@info:
|
||||
@flags:
|
||||
@Returns:
|
||||
|
||||
|
||||
@@ -595,6 +594,7 @@ GType
|
||||
@parent_type:
|
||||
@type_name:
|
||||
@plugin:
|
||||
@flags:
|
||||
@Returns:
|
||||
|
||||
|
||||
@@ -607,6 +607,7 @@ GType
|
||||
@type_name:
|
||||
@info:
|
||||
@finfo:
|
||||
@flags:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
@@ -20,13 +20,16 @@
|
||||
#define __GLIB_GOBJECT_H__
|
||||
|
||||
/* topmost include file for GObject header files */
|
||||
#include <gobject/gtype.h>
|
||||
#include <gobject/gboxed.h>
|
||||
#include <gobject/gbsearcharray.h>
|
||||
#include <gobject/genums.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gvaluetypes.h>
|
||||
#include <gobject/gobject.h>
|
||||
#include <gobject/gparam.h>
|
||||
#include <gobject/gparamspecs.h>
|
||||
#include <gobject/gobject.h>
|
||||
#include <gobject/gsignal.h>
|
||||
#include <gobject/gtype.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gvaluetypes.h>
|
||||
|
||||
|
||||
#endif /* __GLIB_GOBJECT_H__ */
|
||||
|
164
glib/gbsearcharray.c
Normal file
164
glib/gbsearcharray.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#define G_IMPLEMENT_INLINES 1
|
||||
#define __G_BSEARCHARRAY_C__
|
||||
#include "gbsearcharray.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
static inline guint
|
||||
upper_power2 (guint number)
|
||||
{
|
||||
return number ? 1 << g_bit_storage (number - 1) : 0;
|
||||
}
|
||||
|
||||
static inline gpointer
|
||||
bsearch_array_insert (GBSearchArray *barray,
|
||||
gconstpointer key_node,
|
||||
gboolean replace)
|
||||
{
|
||||
gint sizeof_node;
|
||||
guint8 *check;
|
||||
|
||||
sizeof_node = barray->sizeof_node;
|
||||
if (barray->n_nodes == 0)
|
||||
{
|
||||
guint new_size = barray->sizeof_node;
|
||||
|
||||
if (barray->flags & G_BSEARCH_ALIGN_POWER2)
|
||||
new_size = upper_power2 (new_size);
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
barray->n_nodes = 1;
|
||||
check = barray->nodes;
|
||||
replace = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GBSearchCompareFunc cmp_func = barray->cmp_func;
|
||||
guint n_nodes = barray->n_nodes;
|
||||
guint8 *nodes = barray->nodes;
|
||||
gint cmp;
|
||||
guint i;
|
||||
|
||||
nodes -= sizeof_node;
|
||||
do
|
||||
{
|
||||
i = (n_nodes + 1) >> 1;
|
||||
check = nodes + i * sizeof_node;
|
||||
cmp = cmp_func (key_node, check);
|
||||
if (cmp > 0)
|
||||
{
|
||||
n_nodes -= i;
|
||||
nodes = check;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
n_nodes = i - 1;
|
||||
else /* if (cmp == 0) */
|
||||
goto SKIP_GROW;
|
||||
}
|
||||
while (n_nodes);
|
||||
/* grow */
|
||||
if (cmp > 0)
|
||||
check += sizeof_node;
|
||||
i = (check - ((guint8*) barray->nodes)) / sizeof_node;
|
||||
n_nodes = barray->n_nodes++;
|
||||
if (barray->flags & G_BSEARCH_ALIGN_POWER2)
|
||||
{
|
||||
guint new_size = upper_power2 (barray->n_nodes * sizeof_node);
|
||||
guint old_size = upper_power2 (n_nodes * sizeof_node);
|
||||
|
||||
if (new_size != old_size)
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
}
|
||||
else
|
||||
barray->nodes = g_realloc (barray->nodes, barray->n_nodes * sizeof_node);
|
||||
check = barray->nodes + i * sizeof_node;
|
||||
g_memmove (check + sizeof_node, check, (n_nodes - i) * sizeof_node);
|
||||
replace = TRUE;
|
||||
SKIP_GROW:
|
||||
}
|
||||
if (replace)
|
||||
memcpy (check, key_node, sizeof_node);
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_bsearch_array_insert (GBSearchArray *barray,
|
||||
gconstpointer key_node,
|
||||
gboolean replace_existing)
|
||||
{
|
||||
g_return_val_if_fail (barray != NULL, NULL);
|
||||
g_return_val_if_fail (key_node != NULL, NULL);
|
||||
|
||||
return bsearch_array_insert (barray, key_node, replace_existing);
|
||||
}
|
||||
|
||||
void
|
||||
g_bsearch_array_remove_node (GBSearchArray *barray,
|
||||
gpointer _node_in_array)
|
||||
{
|
||||
guint8 *nodes, *bound, *node_in_array = _node_in_array;
|
||||
guint old_size;
|
||||
|
||||
g_return_if_fail (barray != NULL);
|
||||
|
||||
nodes = barray->nodes;
|
||||
old_size = barray->sizeof_node;
|
||||
old_size *= barray->n_nodes; /* beware of int widths */
|
||||
bound = nodes + old_size;
|
||||
|
||||
g_return_if_fail (node_in_array >= nodes && node_in_array < bound);
|
||||
|
||||
bound -= barray->sizeof_node;
|
||||
barray->n_nodes -= 1;
|
||||
g_memmove (node_in_array, node_in_array + barray->sizeof_node, (bound - node_in_array) / barray->sizeof_node);
|
||||
|
||||
if ((barray->flags & G_BSEARCH_DEFER_SHRINK) == 0)
|
||||
{
|
||||
guint new_size = bound - nodes; /* old_size - barray->sizeof_node */
|
||||
|
||||
if (barray->flags & G_BSEARCH_ALIGN_POWER2)
|
||||
{
|
||||
new_size = upper_power2 (new_size);
|
||||
old_size = upper_power2 (old_size);
|
||||
if (old_size != new_size)
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
}
|
||||
else
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_bsearch_array_remove (GBSearchArray *barray,
|
||||
gconstpointer key_node)
|
||||
{
|
||||
gpointer node_in_array;
|
||||
|
||||
g_return_if_fail (barray != NULL);
|
||||
|
||||
node_in_array = g_bsearch_array_lookup (barray, key_node);
|
||||
if (!node_in_array)
|
||||
g_warning (G_STRLOC ": unable to remove unexistant node");
|
||||
else
|
||||
g_bsearch_array_remove_node (barray, node_in_array);
|
||||
}
|
134
glib/gbsearcharray.h
Normal file
134
glib/gbsearcharray.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* gbsearcharray.h: binary searchable sorted array maintenance
|
||||
*/
|
||||
#ifndef __G_BSEARCH_ARRAY_H__
|
||||
#define __G_BSEARCH_ARRAY_H__
|
||||
|
||||
#include <gobject/gtype.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* helper macro to avoid signed overflow for value comparisions */
|
||||
#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) < (v2) ? -1 : (v1) > (v2) ? 1 : 0)
|
||||
|
||||
|
||||
/* --- typedefs --- */
|
||||
typedef struct _GBSearchArray GBSearchArray;
|
||||
typedef gint (*GBSearchCompareFunc) (gconstpointer bsearch_node1,
|
||||
gconstpointer bsearch_node2);
|
||||
typedef enum
|
||||
{
|
||||
G_BSEARCH_ALIGN_POWER2 = 1 << 0,
|
||||
G_BSEARCH_DEFER_SHRINK = 1 << 1
|
||||
} GBSearchFlags;
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
struct _GBSearchArray
|
||||
{
|
||||
GBSearchCompareFunc cmp_func;
|
||||
guint16 sizeof_node;
|
||||
guint16 flags;
|
||||
guint n_nodes;
|
||||
gpointer nodes;
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
gpointer g_bsearch_array_insert (GBSearchArray *barray,
|
||||
gconstpointer key_node,
|
||||
gboolean replace_existing);
|
||||
void g_bsearch_array_remove (GBSearchArray *barray,
|
||||
gconstpointer key_node);
|
||||
void g_bsearch_array_remove_node (GBSearchArray *barray,
|
||||
gpointer node_in_array);
|
||||
G_INLINE_FUNC
|
||||
gpointer g_bsearch_array_lookup (GBSearchArray *barray,
|
||||
gconstpointer key_node);
|
||||
G_INLINE_FUNC
|
||||
gpointer g_bsearch_array_get_nth (GBSearchArray *barray,
|
||||
guint n);
|
||||
|
||||
|
||||
/* --- implementation details --- */
|
||||
#if defined (G_CAN_INLINE) || defined (__G_BSEARCHARRAY_C__)
|
||||
G_INLINE_FUNC gpointer
|
||||
g_bsearch_array_lookup (GBSearchArray *barray,
|
||||
gconstpointer key_node)
|
||||
{
|
||||
if (barray->n_nodes > 0)
|
||||
{
|
||||
GBSearchCompareFunc cmp_func = barray->cmp_func;
|
||||
gint sizeof_node = barray->sizeof_node;
|
||||
guint n_nodes = barray->n_nodes;
|
||||
guint8 *nodes = barray->nodes;
|
||||
|
||||
nodes -= sizeof_node;
|
||||
do
|
||||
{
|
||||
guint8 *check;
|
||||
guint i;
|
||||
register gint cmp;
|
||||
|
||||
i = (n_nodes + 1) >> 1;
|
||||
check = nodes + i * sizeof_node;
|
||||
cmp = cmp_func (key_node, check);
|
||||
if (cmp == 0)
|
||||
return check;
|
||||
else if (cmp > 0)
|
||||
{
|
||||
n_nodes -= i;
|
||||
nodes = check;
|
||||
}
|
||||
else /* if (cmp < 0) */
|
||||
n_nodes = i - 1;
|
||||
}
|
||||
while (n_nodes);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
G_INLINE_FUNC gpointer
|
||||
g_bsearch_array_get_nth (GBSearchArray *barray,
|
||||
guint n)
|
||||
{
|
||||
if (n < barray->n_nodes)
|
||||
{
|
||||
guint8 *nodes = barray->nodes;
|
||||
|
||||
return nodes + n * barray->sizeof_node;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
#endif /* G_CAN_INLINE && __G_BSEARCHARRAY_C__ */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __G_BSEARCH_ARRAY_H__ */
|
@@ -20,13 +20,16 @@
|
||||
#define __GLIB_GOBJECT_H__
|
||||
|
||||
/* topmost include file for GObject header files */
|
||||
#include <gobject/gtype.h>
|
||||
#include <gobject/gboxed.h>
|
||||
#include <gobject/gbsearcharray.h>
|
||||
#include <gobject/genums.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gvaluetypes.h>
|
||||
#include <gobject/gobject.h>
|
||||
#include <gobject/gparam.h>
|
||||
#include <gobject/gparamspecs.h>
|
||||
#include <gobject/gobject.h>
|
||||
#include <gobject/gsignal.h>
|
||||
#include <gobject/gtype.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gvaluetypes.h>
|
||||
|
||||
|
||||
#endif /* __GLIB_GOBJECT_H__ */
|
||||
|
@@ -471,7 +471,7 @@ g_log_default_handler (const gchar *log_domain,
|
||||
*/
|
||||
fd = stdout;
|
||||
#else
|
||||
fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
|
||||
fd = (log_level > G_LOG_LEVEL_MESSAGE) ? 1 : 2;
|
||||
#endif
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
|
@@ -471,7 +471,7 @@ g_log_default_handler (const gchar *log_domain,
|
||||
*/
|
||||
fd = stdout;
|
||||
#else
|
||||
fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
|
||||
fd = (log_level > G_LOG_LEVEL_MESSAGE) ? 1 : 2;
|
||||
#endif
|
||||
|
||||
g_mutex_lock (g_messages_lock);
|
||||
|
@@ -1,3 +1,86 @@
|
||||
Wed Oct 25 20:27:02 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* gtype.c (g_type_free_instance): for the moment, freeing object
|
||||
structures will fill their memory portion with 0xAA. there's a
|
||||
FIXME there, remove this line at a later point.
|
||||
|
||||
Tue Oct 24 23:10:26 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* glib-genmarshal.1:
|
||||
* glib-genmarshal.c: added publically installed marshaller generator.
|
||||
|
||||
* gtype.h: added G_TYPE_INSTANCE_GET_INTERFACE() to retrive a certain
|
||||
interface VTable from instances.
|
||||
|
||||
Mon Oct 23 08:28:15 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* gobject.[hc]: new functions for closure maintenance:
|
||||
(g_object_watch_closure): maintain validity of the object and
|
||||
the closure for objects that are used as data part of a closure.
|
||||
(g_cclosure_new_object): convenience function to create C closures
|
||||
that have an object as data argument.
|
||||
(g_closure_new_object): convenience function to create closures
|
||||
that have an object as data argument.
|
||||
|
||||
* gclosure.[hc]: implementation of GClosure mechanism.
|
||||
a closure is basically an encapsulation of a callback function
|
||||
and its environment. ideally, most places supporting callback
|
||||
functions will simply take a GClosure* pointer and thus unify
|
||||
callback environments wrg destroy notification etc.
|
||||
GClosure provides destroy notifiers for arbitrary data pointers,
|
||||
reference counting, invalidation notification (it can be invalidated
|
||||
which is merely a deactivate state) and a marshallinbg abstraction.
|
||||
GCClosure is also provided in these files, they present a specialized
|
||||
GClosure implementation for C language callbacks.
|
||||
|
||||
* genum.c: macro cleanups.
|
||||
|
||||
* gboxed.[hc]: new files, for boxed type abstraction.
|
||||
(g_boxed_copy): copy a boxed structure
|
||||
(g_boxed_free): free a boxed structure
|
||||
(g_value_set_boxed):
|
||||
(g_value_get_boxed): standard GValue functions for boxed types
|
||||
(g_boxed_type_register_static): convenience function for easy
|
||||
introduction of new G_TYPE_BOXED derivatives.
|
||||
|
||||
* gparam.[hc]: introduced g_param_type_register_static(), a short hand
|
||||
for creation of new GParamSpec derived types.
|
||||
|
||||
* gtype.[hc]: many fixes, introduced ability to flag individual
|
||||
type nodes as ABSTRACT upon registration, added value_peek_pointer()
|
||||
to the value table to peek at GValue contents as a pointer for types
|
||||
that support this. fixed up GValue checks.
|
||||
|
||||
* gvalue.[hc]: added g_value_fits_pointer() and g_value_get_as_pointer()
|
||||
to peek at the value contents as pointer.
|
||||
|
||||
* *.[hc]: adaptions to type macro fixes and changes in the type
|
||||
registration API.
|
||||
|
||||
* many const corrections over the place.
|
||||
|
||||
Sat Oct 21 02:49:56 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* gtype.c (g_type_conforms_to): this function basically behaves like
|
||||
and is_a check, except that it _additionally_ features interfaces
|
||||
for instantiatable types. enforce this in the second branch as well
|
||||
(`type' conforms_to `type') even if `type' is not an interface type.
|
||||
|
||||
Fri Oct 20 15:31:04 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* gvaluetypes.[hc]: added G_TYPE_POINTER implementation from jrb.
|
||||
|
||||
* gtype.[hc]:
|
||||
* gobject.c:
|
||||
* gvaluetypes.c: added GTypeValueTable.value_peek_pointer and
|
||||
suitable implementations of this for G_TYPE_STRING, G_TYPE_OBJECT
|
||||
and G_TYPE_POINTER.
|
||||
|
||||
Mon Aug 21 04:13:37 2000 Tim Janik <timj@gtk.org>
|
||||
|
||||
* gbsearcharray.[hc]: long standing needed generic implementation
|
||||
of a binary searchable, sorted and dynamically sized array.
|
||||
|
||||
2000-10-15 Raja R Harinath <harinath@cs.umn.edu>
|
||||
|
||||
* Makefile.am (BUILT_EXTRA_DIST): New variable.
|
||||
@@ -255,9 +338,5 @@ Sun Apr 2 04:54:36 2000 Tim Janik <timj@gtk.org>
|
||||
* glib-genums.[hc]: enum/flags type implementation, based on
|
||||
bseenum.[hc].
|
||||
|
||||
* glib-extra.[hc]: GLib additions, including 1.3 compatibility
|
||||
routines and various other functions, from string manipulation
|
||||
over list manipulation up to a unix signal GSource.
|
||||
|
||||
* glib-gtype.[hc]: GLib Type System implementation, heavily
|
||||
based on BSE's dynamic type system.
|
||||
|
@@ -3,7 +3,8 @@
|
||||
#
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_builddir) -I. @GLIB_DEBUG_FLAGS@
|
||||
SUBDIRS =
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_builddir) @GLIB_DEBUG_FLAGS@
|
||||
|
||||
# libraries to compile and install
|
||||
lib_LTLIBRARIES = libgobject-1.3.la
|
||||
@@ -22,28 +23,38 @@ libgobject_1_3_la_LIBADD = # $(libglib)
|
||||
# setup source file variables
|
||||
#
|
||||
# GObject header files for public installation (non-generated)
|
||||
gobject_public_h_sources = \
|
||||
gvalue.h \
|
||||
gvaluetypes.h \
|
||||
gparam.h \
|
||||
gparamspecs.h \
|
||||
gobject_public_h_sources = @STRIP_BEGIN@ \
|
||||
gboxed.h \
|
||||
gbsearcharray.h \
|
||||
gclosure.h \
|
||||
genums.h \
|
||||
gobject.h \
|
||||
gparam.h \
|
||||
gparamspecs.h \
|
||||
gsignal.h \
|
||||
gtype.h \
|
||||
gvaluecollector.h
|
||||
gvalue.h \
|
||||
gvaluecollector.h \
|
||||
gvaluetypes.h \
|
||||
@STRIP_END@
|
||||
|
||||
# private GObject header files
|
||||
gobject_private_h_sources =
|
||||
|
||||
# GObject C sources to build the library from
|
||||
gobject_c_sources = \
|
||||
gvalue.c \
|
||||
gvaluetypes.c \
|
||||
gparam.c \
|
||||
gparamspecs.c \
|
||||
gobject_c_sources = @STRIP_BEGIN@ \
|
||||
gboxed.c \
|
||||
gbsearcharray.c \
|
||||
gclosure.c \
|
||||
genums.c \
|
||||
gobject.c \
|
||||
gtype.c
|
||||
gparam.c \
|
||||
gparamspecs.c \
|
||||
gsignal.c \
|
||||
gtype.c \
|
||||
gvalue.c \
|
||||
gvaluetypes.c \
|
||||
@STRIP_END@
|
||||
|
||||
# non-header sources (headers should be specified in the above variables)
|
||||
# that don't serve as direct make target sources, i.e. they don't have
|
||||
@@ -66,12 +77,19 @@ EXTRA_DIST += $(gobject_extra_sources)
|
||||
#
|
||||
# programs to compile and install
|
||||
#
|
||||
bin_PROGRAMS = gobject-query
|
||||
bin_PROGRAMS = gobject-query glib-genmarshal
|
||||
# source files
|
||||
gobject_query_SOURCES = gobject-query.c
|
||||
glib_genmarshal_SOURCES = glib-genmarshal.c
|
||||
# link programs against libgobject
|
||||
progs_LDADD = ../libglib-1.3.la libgobject-1.3.la
|
||||
gobject_query_LDADD = $(progs_LDADD)
|
||||
glib_genmarshal_LDADD = $(progs_LDADD)
|
||||
|
||||
#
|
||||
# manual pages to install
|
||||
#
|
||||
man_MANS = glib-genmarshal.1
|
||||
|
||||
#
|
||||
# auxillary files
|
||||
|
316
gobject/gboxed.c
Normal file
316
gobject/gboxed.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "gboxed.h"
|
||||
|
||||
#include "gbsearcharray.h"
|
||||
#include "gvalue.h"
|
||||
#include "gvaluecollector.h"
|
||||
|
||||
|
||||
|
||||
/* --- typedefs & structures --- */
|
||||
typedef struct
|
||||
{
|
||||
GType type;
|
||||
GBoxedCopyFunc copy;
|
||||
GBoxedFreeFunc free;
|
||||
} BoxedNode;
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
static gint boxed_nodes_cmp (gconstpointer p1,
|
||||
gconstpointer p2);
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
static GBSearchArray boxed_bsa = { boxed_nodes_cmp, sizeof (BoxedNode), 0, 0, NULL };
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
static gint
|
||||
boxed_nodes_cmp (gconstpointer p1,
|
||||
gconstpointer p2)
|
||||
{
|
||||
const BoxedNode *node1 = p1, *node2 = p2;
|
||||
|
||||
return G_BSEARCH_ARRAY_CMP (node1->type, node2->type);
|
||||
}
|
||||
|
||||
void
|
||||
g_boxed_type_init (void) /* sync with gtype.c */
|
||||
{
|
||||
static const GTypeInfo info = {
|
||||
0, /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_destroy */
|
||||
NULL, /* class_init */
|
||||
NULL, /* class_destroy */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
0, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
NULL, /* value_table */
|
||||
};
|
||||
const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
|
||||
GType type;
|
||||
|
||||
/* G_TYPE_BOXED
|
||||
*/
|
||||
type = g_type_register_fundamental (G_TYPE_BOXED, "GBoxed", &info, &finfo, G_TYPE_FLAG_ABSTRACT);
|
||||
g_assert (type == G_TYPE_BOXED);
|
||||
}
|
||||
|
||||
static void
|
||||
boxed_proxy_value_init (GValue *value)
|
||||
{
|
||||
value->data[0].v_pointer = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
boxed_proxy_value_free (GValue *value)
|
||||
{
|
||||
if (value->data[0].v_pointer)
|
||||
{
|
||||
BoxedNode key, *node;
|
||||
|
||||
key.type = value->g_type;
|
||||
node = g_bsearch_array_lookup (&boxed_bsa, &key);
|
||||
node->free (value->data[0].v_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
boxed_proxy_value_copy (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
{
|
||||
if (src_value->data[0].v_pointer)
|
||||
{
|
||||
BoxedNode key, *node;
|
||||
|
||||
key.type = src_value->g_type;
|
||||
node = g_bsearch_array_lookup (&boxed_bsa, &key);
|
||||
dest_value->data[0].v_pointer = node->copy (src_value->data[0].v_pointer);
|
||||
}
|
||||
else
|
||||
dest_value->data[0].v_pointer = src_value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
boxed_proxy_value_peek_pointer (const GValue *value)
|
||||
{
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
boxed_proxy_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
BoxedNode key, *node;
|
||||
|
||||
key.type = value->g_type;
|
||||
node = g_bsearch_array_lookup (&boxed_bsa, &key);
|
||||
value->data[0].v_pointer = node->copy (collect_value->v_pointer);
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
boxed_proxy_lcopy_value (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
BoxedNode key, *node;
|
||||
gpointer *boxed_p = collect_value->v_pointer;
|
||||
|
||||
if (!boxed_p)
|
||||
return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
|
||||
|
||||
key.type = value->g_type;
|
||||
node = g_bsearch_array_lookup (&boxed_bsa, &key);
|
||||
*boxed_p = node->copy (value->data[0].v_pointer);
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GType
|
||||
g_boxed_type_register_static (const gchar *name,
|
||||
GBoxedCopyFunc boxed_copy,
|
||||
GBoxedFreeFunc boxed_free)
|
||||
{
|
||||
static const GTypeValueTable vtable = {
|
||||
boxed_proxy_value_init,
|
||||
boxed_proxy_value_free,
|
||||
boxed_proxy_value_copy,
|
||||
boxed_proxy_value_peek_pointer,
|
||||
G_VALUE_COLLECT_POINTER,
|
||||
boxed_proxy_collect_value,
|
||||
G_VALUE_COLLECT_POINTER,
|
||||
boxed_proxy_lcopy_value,
|
||||
};
|
||||
static const GTypeInfo type_info = {
|
||||
0, /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
NULL, /* class_init */
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
0, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
&vtable, /* value_table */
|
||||
};
|
||||
GType type;
|
||||
|
||||
g_return_val_if_fail (name != NULL, 0);
|
||||
g_return_val_if_fail (boxed_copy != NULL, 0);
|
||||
g_return_val_if_fail (boxed_free != NULL, 0);
|
||||
g_return_val_if_fail (g_type_from_name (name) == 0, 0);
|
||||
|
||||
type = g_type_register_static (G_TYPE_BOXED, name, &type_info, 0);
|
||||
|
||||
/* install proxy functions upon successfull registration */
|
||||
if (type)
|
||||
{
|
||||
BoxedNode key;
|
||||
|
||||
key.type = type;
|
||||
key.copy = boxed_copy;
|
||||
key.free = boxed_free;
|
||||
g_bsearch_array_insert (&boxed_bsa, &key, TRUE);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
GBoxed*
|
||||
g_boxed_copy (GType boxed_type,
|
||||
gpointer src_boxed)
|
||||
{
|
||||
GTypeValueTable *value_table;
|
||||
|
||||
g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
|
||||
g_return_val_if_fail (G_TYPE_IS_ABSTRACT (boxed_type) == FALSE, NULL);
|
||||
g_return_val_if_fail (src_boxed != NULL, NULL);
|
||||
|
||||
value_table = g_type_value_table_peek (boxed_type);
|
||||
if (!value_table)
|
||||
g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type), NULL);
|
||||
|
||||
/* check if our proxying implementation is used, we can short-cut here */
|
||||
if (value_table->value_copy == boxed_proxy_value_copy)
|
||||
{
|
||||
BoxedNode key, *node;
|
||||
|
||||
key.type = boxed_type;
|
||||
node = g_bsearch_array_lookup (&boxed_bsa, &key);
|
||||
src_boxed = node->copy (src_boxed);
|
||||
}
|
||||
else
|
||||
{
|
||||
GValue src_value, dest_value;
|
||||
|
||||
/* we heavil rely on the gvalue.c implementation here */
|
||||
|
||||
memset (&src_value.data, 0, sizeof (src_value.data));
|
||||
memset (&dest_value.data, 0, sizeof (dest_value.data));
|
||||
dest_value.g_type = boxed_type;
|
||||
src_value.g_type = boxed_type;
|
||||
src_value.data[0].v_pointer = src_boxed;
|
||||
value_table->value_copy (&src_value, &dest_value);
|
||||
if (dest_value.data[1].v_ulong ||
|
||||
dest_value.data[2].v_ulong ||
|
||||
dest_value.data[3].v_ulong)
|
||||
g_warning ("the copy_value() implementation of type `%s' seems to make use of reserved GValue fields",
|
||||
g_type_name (boxed_type));
|
||||
|
||||
src_boxed = dest_value.data[0].v_pointer;
|
||||
}
|
||||
|
||||
return src_boxed;
|
||||
}
|
||||
|
||||
void
|
||||
g_boxed_free (GType boxed_type,
|
||||
gpointer boxed)
|
||||
{
|
||||
GTypeValueTable *value_table;
|
||||
|
||||
g_return_if_fail (G_TYPE_IS_BOXED (boxed_type));
|
||||
g_return_if_fail (G_TYPE_IS_ABSTRACT (boxed_type) == FALSE);
|
||||
g_return_if_fail (boxed != NULL);
|
||||
|
||||
value_table = g_type_value_table_peek (boxed_type);
|
||||
if (!value_table)
|
||||
g_return_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type));
|
||||
|
||||
/* check if our proxying implementation is used, we can short-cut here */
|
||||
if (value_table->value_free == boxed_proxy_value_free)
|
||||
{
|
||||
BoxedNode key, *node;
|
||||
|
||||
key.type = boxed_type;
|
||||
node = g_bsearch_array_lookup (&boxed_bsa, &key);
|
||||
node->free (boxed);
|
||||
}
|
||||
else
|
||||
{
|
||||
GValue value;
|
||||
|
||||
/* we heavil rely on the gvalue.c implementation here */
|
||||
memset (&value.data, 0, sizeof (value.data));
|
||||
value.g_type = boxed_type;
|
||||
value.data[0].v_pointer = boxed;
|
||||
value_table->value_free (&value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_value_set_boxed (GValue *value,
|
||||
gpointer boxed)
|
||||
{
|
||||
g_return_if_fail (G_IS_VALUE_BOXED (value));
|
||||
g_return_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value)));
|
||||
|
||||
if (value->data[0].v_pointer)
|
||||
g_boxed_free (G_VALUE_TYPE (value), value->data[0].v_pointer);
|
||||
value->data[0].v_pointer = boxed ? g_boxed_copy (G_VALUE_TYPE (value), boxed) : NULL;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_value_get_boxed (GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_BOXED (value), NULL);
|
||||
g_return_val_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value)), NULL);
|
||||
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_value_dup_boxed (GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_BOXED (value), NULL);
|
||||
g_return_val_if_fail (G_TYPE_IS_VALUE (G_VALUE_TYPE (value)), NULL);
|
||||
|
||||
return value->data[0].v_pointer ? g_boxed_copy (G_VALUE_TYPE (value), value->data[0].v_pointer) : NULL;
|
||||
}
|
64
gobject/gboxed.h
Normal file
64
gobject/gboxed.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __G_BOXED_H__
|
||||
#define __G_BOXED_H__
|
||||
|
||||
#include <gobject/gtype.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* --- type macros --- */
|
||||
#define G_TYPE_IS_BOXED(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED)
|
||||
#define G_IS_VALUE_BOXED(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_BOXED))
|
||||
|
||||
|
||||
/* --- typedefs --- */
|
||||
typedef struct _GBoxed GBoxed;
|
||||
typedef gpointer (*GBoxedCopyFunc) (gpointer boxed);
|
||||
typedef void (*GBoxedFreeFunc) (gpointer boxed);
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
GBoxed* g_boxed_copy (GType boxed_type,
|
||||
gpointer src_boxed);
|
||||
void g_boxed_free (GType boxed_type,
|
||||
gpointer boxed);
|
||||
void g_value_set_boxed (GValue *value,
|
||||
gpointer boxed);
|
||||
gpointer g_value_get_boxed (GValue *value);
|
||||
gpointer g_value_dup_boxed (GValue *value);
|
||||
|
||||
|
||||
/* --- convenience --- */
|
||||
GType g_boxed_type_register_static (const gchar *name,
|
||||
GBoxedCopyFunc boxed_copy,
|
||||
GBoxedFreeFunc boxed_free);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __G_BOXED_H__ */
|
164
gobject/gbsearcharray.c
Normal file
164
gobject/gbsearcharray.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#define G_IMPLEMENT_INLINES 1
|
||||
#define __G_BSEARCHARRAY_C__
|
||||
#include "gbsearcharray.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
static inline guint
|
||||
upper_power2 (guint number)
|
||||
{
|
||||
return number ? 1 << g_bit_storage (number - 1) : 0;
|
||||
}
|
||||
|
||||
static inline gpointer
|
||||
bsearch_array_insert (GBSearchArray *barray,
|
||||
gconstpointer key_node,
|
||||
gboolean replace)
|
||||
{
|
||||
gint sizeof_node;
|
||||
guint8 *check;
|
||||
|
||||
sizeof_node = barray->sizeof_node;
|
||||
if (barray->n_nodes == 0)
|
||||
{
|
||||
guint new_size = barray->sizeof_node;
|
||||
|
||||
if (barray->flags & G_BSEARCH_ALIGN_POWER2)
|
||||
new_size = upper_power2 (new_size);
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
barray->n_nodes = 1;
|
||||
check = barray->nodes;
|
||||
replace = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GBSearchCompareFunc cmp_func = barray->cmp_func;
|
||||
guint n_nodes = barray->n_nodes;
|
||||
guint8 *nodes = barray->nodes;
|
||||
gint cmp;
|
||||
guint i;
|
||||
|
||||
nodes -= sizeof_node;
|
||||
do
|
||||
{
|
||||
i = (n_nodes + 1) >> 1;
|
||||
check = nodes + i * sizeof_node;
|
||||
cmp = cmp_func (key_node, check);
|
||||
if (cmp > 0)
|
||||
{
|
||||
n_nodes -= i;
|
||||
nodes = check;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
n_nodes = i - 1;
|
||||
else /* if (cmp == 0) */
|
||||
goto SKIP_GROW;
|
||||
}
|
||||
while (n_nodes);
|
||||
/* grow */
|
||||
if (cmp > 0)
|
||||
check += sizeof_node;
|
||||
i = (check - ((guint8*) barray->nodes)) / sizeof_node;
|
||||
n_nodes = barray->n_nodes++;
|
||||
if (barray->flags & G_BSEARCH_ALIGN_POWER2)
|
||||
{
|
||||
guint new_size = upper_power2 (barray->n_nodes * sizeof_node);
|
||||
guint old_size = upper_power2 (n_nodes * sizeof_node);
|
||||
|
||||
if (new_size != old_size)
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
}
|
||||
else
|
||||
barray->nodes = g_realloc (barray->nodes, barray->n_nodes * sizeof_node);
|
||||
check = barray->nodes + i * sizeof_node;
|
||||
g_memmove (check + sizeof_node, check, (n_nodes - i) * sizeof_node);
|
||||
replace = TRUE;
|
||||
SKIP_GROW:
|
||||
}
|
||||
if (replace)
|
||||
memcpy (check, key_node, sizeof_node);
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_bsearch_array_insert (GBSearchArray *barray,
|
||||
gconstpointer key_node,
|
||||
gboolean replace_existing)
|
||||
{
|
||||
g_return_val_if_fail (barray != NULL, NULL);
|
||||
g_return_val_if_fail (key_node != NULL, NULL);
|
||||
|
||||
return bsearch_array_insert (barray, key_node, replace_existing);
|
||||
}
|
||||
|
||||
void
|
||||
g_bsearch_array_remove_node (GBSearchArray *barray,
|
||||
gpointer _node_in_array)
|
||||
{
|
||||
guint8 *nodes, *bound, *node_in_array = _node_in_array;
|
||||
guint old_size;
|
||||
|
||||
g_return_if_fail (barray != NULL);
|
||||
|
||||
nodes = barray->nodes;
|
||||
old_size = barray->sizeof_node;
|
||||
old_size *= barray->n_nodes; /* beware of int widths */
|
||||
bound = nodes + old_size;
|
||||
|
||||
g_return_if_fail (node_in_array >= nodes && node_in_array < bound);
|
||||
|
||||
bound -= barray->sizeof_node;
|
||||
barray->n_nodes -= 1;
|
||||
g_memmove (node_in_array, node_in_array + barray->sizeof_node, (bound - node_in_array) / barray->sizeof_node);
|
||||
|
||||
if ((barray->flags & G_BSEARCH_DEFER_SHRINK) == 0)
|
||||
{
|
||||
guint new_size = bound - nodes; /* old_size - barray->sizeof_node */
|
||||
|
||||
if (barray->flags & G_BSEARCH_ALIGN_POWER2)
|
||||
{
|
||||
new_size = upper_power2 (new_size);
|
||||
old_size = upper_power2 (old_size);
|
||||
if (old_size != new_size)
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
}
|
||||
else
|
||||
barray->nodes = g_realloc (barray->nodes, new_size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_bsearch_array_remove (GBSearchArray *barray,
|
||||
gconstpointer key_node)
|
||||
{
|
||||
gpointer node_in_array;
|
||||
|
||||
g_return_if_fail (barray != NULL);
|
||||
|
||||
node_in_array = g_bsearch_array_lookup (barray, key_node);
|
||||
if (!node_in_array)
|
||||
g_warning (G_STRLOC ": unable to remove unexistant node");
|
||||
else
|
||||
g_bsearch_array_remove_node (barray, node_in_array);
|
||||
}
|
134
gobject/gbsearcharray.h
Normal file
134
gobject/gbsearcharray.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Tim Janik
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* gbsearcharray.h: binary searchable sorted array maintenance
|
||||
*/
|
||||
#ifndef __G_BSEARCH_ARRAY_H__
|
||||
#define __G_BSEARCH_ARRAY_H__
|
||||
|
||||
#include <gobject/gtype.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* helper macro to avoid signed overflow for value comparisions */
|
||||
#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) < (v2) ? -1 : (v1) > (v2) ? 1 : 0)
|
||||
|
||||
|
||||
/* --- typedefs --- */
|
||||
typedef struct _GBSearchArray GBSearchArray;
|
||||
typedef gint (*GBSearchCompareFunc) (gconstpointer bsearch_node1,
|
||||
gconstpointer bsearch_node2);
|
||||
typedef enum
|
||||
{
|
||||
G_BSEARCH_ALIGN_POWER2 = 1 << 0,
|
||||
G_BSEARCH_DEFER_SHRINK = 1 << 1
|
||||
} GBSearchFlags;
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
struct _GBSearchArray
|
||||
{
|
||||
GBSearchCompareFunc cmp_func;
|
||||
guint16 sizeof_node;
|
||||
guint16 flags;
|
||||
guint n_nodes;
|
||||
gpointer nodes;
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
gpointer g_bsearch_array_insert (GBSearchArray *barray,
|
||||
gconstpointer key_node,
|
||||
gboolean replace_existing);
|
||||
void g_bsearch_array_remove (GBSearchArray *barray,
|
||||
gconstpointer key_node);
|
||||
void g_bsearch_array_remove_node (GBSearchArray *barray,
|
||||
gpointer node_in_array);
|
||||
G_INLINE_FUNC
|
||||
gpointer g_bsearch_array_lookup (GBSearchArray *barray,
|
||||
gconstpointer key_node);
|
||||
G_INLINE_FUNC
|
||||
gpointer g_bsearch_array_get_nth (GBSearchArray *barray,
|
||||
guint n);
|
||||
|
||||
|
||||
/* --- implementation details --- */
|
||||
#if defined (G_CAN_INLINE) || defined (__G_BSEARCHARRAY_C__)
|
||||
G_INLINE_FUNC gpointer
|
||||
g_bsearch_array_lookup (GBSearchArray *barray,
|
||||
gconstpointer key_node)
|
||||
{
|
||||
if (barray->n_nodes > 0)
|
||||
{
|
||||
GBSearchCompareFunc cmp_func = barray->cmp_func;
|
||||
gint sizeof_node = barray->sizeof_node;
|
||||
guint n_nodes = barray->n_nodes;
|
||||
guint8 *nodes = barray->nodes;
|
||||
|
||||
nodes -= sizeof_node;
|
||||
do
|
||||
{
|
||||
guint8 *check;
|
||||
guint i;
|
||||
register gint cmp;
|
||||
|
||||
i = (n_nodes + 1) >> 1;
|
||||
check = nodes + i * sizeof_node;
|
||||
cmp = cmp_func (key_node, check);
|
||||
if (cmp == 0)
|
||||
return check;
|
||||
else if (cmp > 0)
|
||||
{
|
||||
n_nodes -= i;
|
||||
nodes = check;
|
||||
}
|
||||
else /* if (cmp < 0) */
|
||||
n_nodes = i - 1;
|
||||
}
|
||||
while (n_nodes);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
G_INLINE_FUNC gpointer
|
||||
g_bsearch_array_get_nth (GBSearchArray *barray,
|
||||
guint n)
|
||||
{
|
||||
if (n < barray->n_nodes)
|
||||
{
|
||||
guint8 *nodes = barray->nodes;
|
||||
|
||||
return nodes + n * barray->sizeof_node;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
#endif /* G_CAN_INLINE && __G_BSEARCHARRAY_C__ */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __G_BSEARCH_ARRAY_H__ */
|
534
gobject/gclosure.c
Normal file
534
gobject/gclosure.c
Normal file
@@ -0,0 +1,534 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "gclosure.h"
|
||||
|
||||
#include "gvalue.h"
|
||||
|
||||
|
||||
/* FIXME: need caching allocators
|
||||
*/
|
||||
|
||||
#define CLOSURE_MAX_REF_COUNT ((1 << 15) - 1)
|
||||
#define CLOSURE_MAX_N_GUARDS ((1 << 1) - 1)
|
||||
#define CLOSURE_MAX_N_FNOTIFIERS ((1 << 2) - 1)
|
||||
#define CLOSURE_MAX_N_INOTIFIERS ((1 << 8) - 1)
|
||||
#define CLOSURE_N_MFUNCS(cl) ((cl)->meta_marshal + \
|
||||
((cl)->n_guards << 1L))
|
||||
#define CLOSURE_N_NOTIFIERS(cl) (CLOSURE_N_MFUNCS (cl) + \
|
||||
(cl)->n_fnotifiers + \
|
||||
(cl)->n_inotifiers)
|
||||
enum {
|
||||
FNOTIFY,
|
||||
INOTIFY,
|
||||
PRE_NOTIFY,
|
||||
POST_NOTIFY
|
||||
};
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
GClosure*
|
||||
g_closure_new_simple (guint sizeof_closure,
|
||||
gpointer data)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (sizeof_closure >= sizeof (GClosure), NULL);
|
||||
|
||||
closure = g_malloc (sizeof_closure);
|
||||
closure->ref_count = 1;
|
||||
closure->meta_marshal = 0;
|
||||
closure->n_guards = 0;
|
||||
closure->n_fnotifiers = 0;
|
||||
closure->n_inotifiers = 0;
|
||||
closure->in_inotify = FALSE;
|
||||
closure->floating = TRUE;
|
||||
closure->derivative_flag = 0;
|
||||
closure->in_marshal = FALSE;
|
||||
closure->is_invalid = FALSE;
|
||||
closure->marshal = NULL;
|
||||
closure->data = data;
|
||||
closure->notifiers = NULL;
|
||||
memset (G_STRUCT_MEMBER_P (closure, sizeof (*closure)), 0, sizeof_closure - sizeof (*closure));
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
static inline void
|
||||
closure_invoke_notifiers (GClosure *closure,
|
||||
guint notify_type)
|
||||
{
|
||||
/* notifier layout:
|
||||
* meta_marshal n_guards n_guards n_fnotif. n_inotifiers
|
||||
* ->[[meta_marshal][pre_guards][post_guards][fnotifers][inotifiers]]
|
||||
*
|
||||
* CLOSURE_N_MFUNCS(cl) = meta_marshal + n_guards + n_guards;
|
||||
* CLOSURE_N_NOTIFIERS(cl) = CLOSURE_N_MFUNCS(cl) + n_fnotifiers + n_inotifiers
|
||||
*
|
||||
* constrains/catches:
|
||||
* - closure->notifiers may be reloacted during callback
|
||||
* - closure->n_fnotifiers and closure->n_inotifiers may change during callback
|
||||
* - i.e. callbacks can be removed/added during invocation
|
||||
* - have to prepare for callback removal during invocation (->marshal & ->data)
|
||||
* - have to distinguish (->marshal & ->data) for INOTIFY/FNOTIFY (->in_inotify)
|
||||
* + closure->n_guards is const during PRE_NOTIFY & POST_NOTIFY
|
||||
* + closure->meta_marshal is const for all cases
|
||||
* + none of the callbacks can cause recursion
|
||||
* + closure->n_inotifiers is const 0 during FNOTIFY
|
||||
*/
|
||||
switch (notify_type)
|
||||
{
|
||||
GClosureNotifyData *ndata;
|
||||
guint i, offs;
|
||||
case FNOTIFY:
|
||||
while (closure->n_fnotifiers)
|
||||
{
|
||||
register guint n = --closure->n_fnotifiers;
|
||||
|
||||
ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + n;
|
||||
closure->marshal = (gpointer) ndata->notify;
|
||||
closure->data = ndata->data;
|
||||
ndata->notify (ndata->data, closure);
|
||||
}
|
||||
closure->marshal = NULL;
|
||||
closure->data = NULL;
|
||||
break;
|
||||
case INOTIFY:
|
||||
closure->in_inotify = TRUE;
|
||||
while (closure->n_inotifiers)
|
||||
{
|
||||
register guint n = --closure->n_inotifiers;
|
||||
|
||||
ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + n;
|
||||
closure->marshal = (gpointer) ndata->notify;
|
||||
closure->data = ndata->data;
|
||||
ndata->notify (ndata->data, closure);
|
||||
}
|
||||
closure->marshal = NULL;
|
||||
closure->data = NULL;
|
||||
closure->in_inotify = FALSE;
|
||||
break;
|
||||
case PRE_NOTIFY:
|
||||
i = closure->n_guards;
|
||||
offs = closure->meta_marshal;
|
||||
while (i--)
|
||||
{
|
||||
ndata = closure->notifiers + offs + i;
|
||||
ndata->notify (ndata->data, closure);
|
||||
}
|
||||
break;
|
||||
case POST_NOTIFY:
|
||||
i = closure->n_guards;
|
||||
offs = closure->meta_marshal + i;
|
||||
while (i--)
|
||||
{
|
||||
ndata = closure->notifiers + offs + i;
|
||||
ndata->notify (ndata->data, closure);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_set_meta_marshal (GClosure *closure,
|
||||
gpointer marshal_data,
|
||||
GClosureMarshal meta_marshal)
|
||||
{
|
||||
GClosureNotifyData *notifiers;
|
||||
guint n;
|
||||
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (meta_marshal != NULL);
|
||||
g_return_if_fail (closure->is_invalid == FALSE);
|
||||
g_return_if_fail (closure->in_marshal == FALSE);
|
||||
g_return_if_fail (closure->meta_marshal == FALSE);
|
||||
|
||||
n = CLOSURE_N_NOTIFIERS (closure);
|
||||
notifiers = closure->notifiers;
|
||||
closure->notifiers = g_renew (GClosureNotifyData, NULL, CLOSURE_N_NOTIFIERS (closure) + 1);
|
||||
closure->notifiers[0].data = marshal_data;
|
||||
closure->notifiers[0].notify = (GClosureNotify) meta_marshal;
|
||||
if (notifiers)
|
||||
{
|
||||
/* usually the meta marshal will be setup right after creation, so the
|
||||
* memcpy() should be rare-case scenario
|
||||
*/
|
||||
memcpy (closure->notifiers + 1, notifiers, CLOSURE_N_NOTIFIERS (closure) * sizeof (notifiers[0]));
|
||||
g_free (notifiers);
|
||||
}
|
||||
closure->meta_marshal = 1;
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_add_marshal_guards (GClosure *closure,
|
||||
gpointer pre_marshal_data,
|
||||
GClosureNotify pre_marshal_notify,
|
||||
gpointer post_marshal_data,
|
||||
GClosureNotify post_marshal_notify)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (pre_marshal_notify != NULL);
|
||||
g_return_if_fail (post_marshal_notify != NULL);
|
||||
g_return_if_fail (closure->is_invalid == FALSE);
|
||||
g_return_if_fail (closure->in_marshal == FALSE);
|
||||
g_return_if_fail (closure->n_guards < CLOSURE_MAX_N_GUARDS);
|
||||
|
||||
closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 2);
|
||||
if (closure->n_inotifiers)
|
||||
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers +
|
||||
closure->n_inotifiers + 1)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers + 0)];
|
||||
if (closure->n_inotifiers > 1)
|
||||
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers +
|
||||
closure->n_inotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers + 1)];
|
||||
if (closure->n_fnotifiers)
|
||||
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers + 1)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 0];
|
||||
if (closure->n_fnotifiers > 1)
|
||||
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 1];
|
||||
if (closure->n_guards)
|
||||
closure->notifiers[(closure->meta_marshal +
|
||||
closure->n_guards +
|
||||
closure->n_guards + 1)] = closure->notifiers[closure->meta_marshal + closure->n_guards];
|
||||
i = closure->n_guards++;
|
||||
closure->notifiers[closure->meta_marshal + i].data = pre_marshal_data;
|
||||
closure->notifiers[closure->meta_marshal + i].notify = pre_marshal_notify;
|
||||
closure->notifiers[closure->meta_marshal + i + i].data = post_marshal_data;
|
||||
closure->notifiers[closure->meta_marshal + i + i].notify = post_marshal_notify;
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_add_fnotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (notify_func != NULL);
|
||||
g_return_if_fail (closure->n_fnotifiers < CLOSURE_MAX_N_FNOTIFIERS);
|
||||
|
||||
closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 1);
|
||||
if (closure->n_inotifiers)
|
||||
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers +
|
||||
closure->n_inotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers + 0)];
|
||||
i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers++;
|
||||
closure->notifiers[i].data = notify_data;
|
||||
closure->notifiers[i].notify = notify_func;
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_add_inotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (notify_func != NULL);
|
||||
g_return_if_fail (closure->is_invalid == FALSE);
|
||||
g_return_if_fail (closure->n_inotifiers < CLOSURE_MAX_N_INOTIFIERS);
|
||||
|
||||
closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 1);
|
||||
i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + closure->n_inotifiers++;
|
||||
closure->notifiers[i].data = notify_data;
|
||||
closure->notifiers[i].notify = notify_func;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
closure_try_remove_inotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func)
|
||||
{
|
||||
GClosureNotifyData *ndata, *nlast;
|
||||
|
||||
nlast = closure->notifiers + CLOSURE_N_NOTIFIERS (closure) - 1;
|
||||
for (ndata = nlast + 1 - closure->n_inotifiers; ndata <= nlast; ndata++)
|
||||
if (ndata->notify == notify_func && ndata->data == notify_data)
|
||||
{
|
||||
closure->n_inotifiers -= 1;
|
||||
if (ndata < nlast)
|
||||
*ndata = *nlast;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
closure_try_remove_fnotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func)
|
||||
{
|
||||
GClosureNotifyData *ndata, *nlast;
|
||||
|
||||
nlast = closure->notifiers + CLOSURE_N_NOTIFIERS (closure) - closure->n_inotifiers - 1;
|
||||
for (ndata = nlast + 1 - closure->n_fnotifiers; ndata <= nlast; ndata++)
|
||||
if (ndata->notify == notify_func && ndata->data == notify_data)
|
||||
{
|
||||
closure->n_fnotifiers -= 1;
|
||||
if (ndata < nlast)
|
||||
*ndata = *nlast;
|
||||
if (closure->n_inotifiers)
|
||||
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
|
||||
closure->n_fnotifiers +
|
||||
closure->n_inotifiers)];
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_closure_ref (GClosure *closure)
|
||||
{
|
||||
g_return_val_if_fail (closure != NULL, NULL);
|
||||
g_return_val_if_fail (closure->ref_count > 0, NULL);
|
||||
g_return_val_if_fail (closure->ref_count < CLOSURE_MAX_REF_COUNT, NULL);
|
||||
|
||||
/* floating is basically a kludge to avoid creating closures
|
||||
* with a ref_count of 0. so the first one doing _ref() will
|
||||
* own the closure's initial ref_count
|
||||
*/
|
||||
if (closure->floating)
|
||||
closure->floating = FALSE;
|
||||
else
|
||||
closure->ref_count += 1;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_invalidate (GClosure *closure)
|
||||
{
|
||||
g_return_if_fail (closure != NULL);
|
||||
|
||||
if (!closure->is_invalid)
|
||||
{
|
||||
closure->ref_count += 1; /* preserve floating flag */
|
||||
closure->is_invalid = TRUE;
|
||||
closure_invoke_notifiers (closure, INOTIFY);
|
||||
g_closure_unref (closure);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_unref (GClosure *closure)
|
||||
{
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (closure->ref_count > 0);
|
||||
|
||||
if (closure->ref_count == 1) /* last unref, invalidate first */
|
||||
g_closure_invalidate (closure);
|
||||
|
||||
closure->ref_count -= 1;
|
||||
|
||||
if (closure->ref_count == 0)
|
||||
{
|
||||
closure_invoke_notifiers (closure, FNOTIFY);
|
||||
g_free (closure);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_remove_inotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func)
|
||||
{
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (notify_func != NULL);
|
||||
|
||||
if (closure->is_invalid && closure->in_inotify && /* account removal of notify_func() while its called */
|
||||
((gpointer) closure->marshal) == ((gpointer) notify_func) && closure->data == notify_data)
|
||||
closure->marshal = NULL;
|
||||
else if (!closure_try_remove_inotify (closure, notify_data, notify_func))
|
||||
g_warning (G_STRLOC ": unable to remove uninstalled invalidation notifier: %p (%p)",
|
||||
notify_func, notify_data);
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_remove_fnotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func)
|
||||
{
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (notify_func != NULL);
|
||||
|
||||
if (closure->is_invalid && !closure->in_inotify && /* account removal of notify_func() while its called */
|
||||
((gpointer) closure->marshal) == ((gpointer) notify_func) && closure->data == notify_data)
|
||||
closure->marshal = NULL;
|
||||
else if (!closure_try_remove_fnotify (closure, notify_data, notify_func))
|
||||
g_warning (G_STRLOC ": unable to remove uninstalled finalization notifier: %p (%p)",
|
||||
notify_func, notify_data);
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_invoke (GClosure *closure,
|
||||
guint invocation_hint,
|
||||
GValue /*out*/ *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values)
|
||||
{
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (closure->marshal || closure->meta_marshal);
|
||||
|
||||
if (!closure->is_invalid)
|
||||
{
|
||||
GClosureMarshal marshal;
|
||||
gpointer marshal_data;
|
||||
gboolean in_marshal = closure->in_marshal;
|
||||
|
||||
closure->ref_count += 1; /* preserve floating flag */
|
||||
closure->in_marshal = TRUE;
|
||||
if (closure->meta_marshal)
|
||||
{
|
||||
marshal_data = closure->notifiers[0].data;
|
||||
marshal = (GClosureMarshal) closure->notifiers[0].notify;
|
||||
}
|
||||
else
|
||||
{
|
||||
marshal_data = NULL;
|
||||
marshal = closure->marshal;
|
||||
}
|
||||
if (!in_marshal)
|
||||
closure_invoke_notifiers (closure, PRE_NOTIFY);
|
||||
marshal (closure, invocation_hint,
|
||||
return_value,
|
||||
n_param_values, param_values,
|
||||
marshal_data);
|
||||
if (!in_marshal)
|
||||
closure_invoke_notifiers (closure, POST_NOTIFY);
|
||||
closure->in_marshal = in_marshal;
|
||||
g_closure_unref (closure);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
g_closure_set_marshal (GClosure *closure,
|
||||
GClosureMarshal marshal)
|
||||
{
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (marshal != NULL);
|
||||
|
||||
if (closure->marshal && closure->marshal != marshal)
|
||||
g_warning ("attempt to override closure->marshal (%p) with new marshal (%p)",
|
||||
closure->marshal, marshal);
|
||||
else
|
||||
closure->marshal = marshal;
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_cclosure_new (GCallback callback_func,
|
||||
gpointer user_data,
|
||||
GClosureNotify destroy_data)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (callback_func != NULL, NULL);
|
||||
|
||||
closure = g_closure_new_simple (sizeof (GCClosure), user_data);
|
||||
if (destroy_data)
|
||||
g_closure_add_fnotify (closure, user_data, destroy_data);
|
||||
((GCClosure*) closure)->callback = callback_func;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_cclosure_new_swap (GCallback callback_func,
|
||||
gpointer user_data,
|
||||
GClosureNotify destroy_data)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (callback_func != NULL, NULL);
|
||||
|
||||
closure = g_closure_new_simple (sizeof (GCClosure), user_data);
|
||||
if (destroy_data)
|
||||
g_closure_add_fnotify (closure, user_data, destroy_data);
|
||||
((GCClosure*) closure)->callback = callback_func;
|
||||
closure->derivative_flag = TRUE;
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
static void
|
||||
g_type_class_meta_marshal (GClosure *closure,
|
||||
guint invocation_hint,
|
||||
GValue /*out*/ *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer marshal_data)
|
||||
{
|
||||
GTypeClass *class;
|
||||
gpointer callback;
|
||||
/* GType itype = GPOINTER_TO_UINT (closure->data); */
|
||||
guint offset = GPOINTER_TO_UINT (marshal_data);
|
||||
|
||||
class = G_TYPE_INSTANCE_GET_CLASS (g_value_get_as_pointer (param_values + 0), itype, GTypeClass);
|
||||
callback = G_STRUCT_MEMBER (gpointer, class, offset);
|
||||
if (callback)
|
||||
closure->marshal (closure, invocation_hint, return_value,
|
||||
n_param_values, param_values, callback);
|
||||
}
|
||||
|
||||
static void
|
||||
g_type_iface_meta_marshal (GClosure *closure,
|
||||
guint invocation_hint,
|
||||
GValue /*out*/ *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer marshal_data)
|
||||
{
|
||||
GTypeClass *class;
|
||||
gpointer callback;
|
||||
GType itype = GPOINTER_TO_UINT (closure->data);
|
||||
guint offset = GPOINTER_TO_UINT (marshal_data);
|
||||
|
||||
class = G_TYPE_INSTANCE_GET_INTERFACE (g_value_get_as_pointer (param_values + 0), itype, GTypeClass);
|
||||
callback = G_STRUCT_MEMBER (gpointer, class, offset);
|
||||
if (callback)
|
||||
closure->marshal (closure, invocation_hint, return_value,
|
||||
n_param_values, param_values, callback);
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_signal_type_closure_new (GType itype,
|
||||
guint struct_offset)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (G_TYPE_IS_CLASSED (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
|
||||
g_return_val_if_fail (struct_offset >= sizeof (GTypeClass), NULL);
|
||||
|
||||
closure = g_closure_new_simple (sizeof (GClosure), GUINT_TO_POINTER (itype));
|
||||
if (G_TYPE_IS_INTERFACE (itype))
|
||||
g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_iface_meta_marshal);
|
||||
else
|
||||
g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_class_meta_marshal);
|
||||
|
||||
return closure;
|
||||
}
|
185
gobject/gclosure.h
Normal file
185
gobject/gclosure.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __G_CLOSURE_H__
|
||||
#define __G_CLOSURE_H__
|
||||
|
||||
|
||||
#include <gobject/gtype.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
/* --- defines --- */
|
||||
#define G_CLOSURE_NEEDS_MARSHAL(closure) (((GClosure*) (closure))->marshal == NULL)
|
||||
#define G_CCLOSURE_SWAP_DATA(cclosure) (((GClosure*) (closure))->derivative_flag)
|
||||
|
||||
|
||||
/* -- typedefs --- */
|
||||
typedef struct _GClosure GClosure;
|
||||
typedef struct _GClosureNotifyData GClosureNotifyData;
|
||||
typedef gpointer GCallback;
|
||||
typedef void (*GClosureNotify) (gpointer data,
|
||||
GClosure *closure);
|
||||
typedef void (*GClosureMarshal) (GClosure *closure,
|
||||
guint invocation_hint,
|
||||
GValue *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer marshal_data);
|
||||
typedef struct _GCClosure GCClosure;
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
struct _GClosureNotifyData
|
||||
{
|
||||
gpointer data;
|
||||
GClosureNotify notify;
|
||||
};
|
||||
struct _GClosure
|
||||
{
|
||||
/*< private >*/ guint ref_count : 15;
|
||||
/*< private >*/ guint meta_marshal : 1;
|
||||
/*< private >*/ guint n_guards : 1;
|
||||
/*< private >*/ guint n_fnotifiers : 2; /* finalization notifiers */
|
||||
/*< private >*/ guint n_inotifiers : 8; /* invalidation notifiers */
|
||||
/*< private >*/ guint in_inotify : 1;
|
||||
/*< private >*/ guint floating : 1;
|
||||
/*< protected >*/ guint derivative_flag : 1;
|
||||
/*< puplic >*/ guint in_marshal : 1;
|
||||
/*< public >*/ guint is_invalid : 1;
|
||||
|
||||
/*< private >*/ void (*marshal) (GClosure *closure,
|
||||
guint invocation_hint,
|
||||
GValue /*out*/ *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer marshal_data);
|
||||
/*< protected >*/ gpointer data;
|
||||
|
||||
/*< private >*/ GClosureNotifyData *notifiers;
|
||||
|
||||
/* invariants/constrains:
|
||||
* - ->marshal and ->data are _invalid_ as soon as ->is_invalid==TRUE
|
||||
* - invocation of all inotifiers occours prior to fnotifiers
|
||||
* - order of inotifiers is random
|
||||
* inotifiers may _not_ free/invalidate parameter values (e.g. ->data)
|
||||
* - order of fnotifiers is random
|
||||
* - notifiers may only be removed before or during their invocation
|
||||
* - reference counting may only happen prior to fnotify invocation
|
||||
* (in that sense, fnotifiers are really finalization handlers)
|
||||
*/
|
||||
};
|
||||
/* closure for C function calls, callback() is the user function
|
||||
*/
|
||||
struct _GCClosure
|
||||
{
|
||||
GClosure closure;
|
||||
gpointer callback;
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
GClosure* g_cclosure_new (GCallback callback_func,
|
||||
gpointer user_data,
|
||||
GClosureNotify destroy_data);
|
||||
GClosure* g_cclosure_new_swap (GCallback callback_func,
|
||||
gpointer user_data,
|
||||
GClosureNotify destroy_data);
|
||||
GClosure* g_signal_type_closure_new (GType itype,
|
||||
guint struct_offset);
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
GClosure* g_closure_ref (GClosure *closure);
|
||||
void g_closure_unref (GClosure *closure);
|
||||
/* intimidating */
|
||||
GClosure* g_closure_new_simple (guint sizeof_closure,
|
||||
gpointer data);
|
||||
void g_closure_add_fnotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func);
|
||||
void g_closure_remove_fnotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func);
|
||||
void g_closure_add_inotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func);
|
||||
void g_closure_remove_inotify (GClosure *closure,
|
||||
gpointer notify_data,
|
||||
GClosureNotify notify_func);
|
||||
void g_closure_add_marshal_guards (GClosure *closure,
|
||||
gpointer pre_marshal_data,
|
||||
GClosureNotify pre_marshal_notify,
|
||||
gpointer post_marshal_data,
|
||||
GClosureNotify post_marshal_notify);
|
||||
void g_closure_set_marshal (GClosure *closure,
|
||||
GClosureMarshal marshal);
|
||||
void g_closure_set_meta_marshal (GClosure *closure,
|
||||
gpointer marshal_data,
|
||||
GClosureMarshal meta_marshal);
|
||||
void g_closure_invalidate (GClosure *closure);
|
||||
void g_closure_invoke (GClosure *closure,
|
||||
guint invocation_hint,
|
||||
GValue /*out*/ *return_value,
|
||||
guint n_param_values,
|
||||
const GValue *param_values);
|
||||
|
||||
|
||||
/*
|
||||
data_object::destroy -> closure_invalidate();
|
||||
closure_invalidate() -> disconnect(closure);
|
||||
disconnect(closure) -> (unlink) closure_unref();
|
||||
closure_finalize() -> g_free (data_string);
|
||||
|
||||
1) need GObject and GType in glib
|
||||
2) need GParam
|
||||
3) need to resolve dtor cycles
|
||||
4) need GSignal move
|
||||
5) destroy on last caller ref or last data ref?
|
||||
|
||||
|
||||
random remarks:
|
||||
- don't mandate signals for GObject
|
||||
- OTOH, don't mandate GObject for GSignal
|
||||
- need marshaller repo with decent aliasing to base types
|
||||
- provide marshaller collection, virtually covering anything out there
|
||||
- at that point, still need GSignalCMarhsaller to g_signal_new() ?
|
||||
- can we combine varargs collect mechanisms with marshaller stubs?
|
||||
for out values (i.e. returntypes), that might get rid of the following
|
||||
point...
|
||||
- char* return signals with connections ala:
|
||||
connect({ return "static data that can't work"; }),
|
||||
connect({ return g_strdup ("properly duplicated string"); })
|
||||
won't work anymore. CRASH
|
||||
|
||||
problems:
|
||||
- accumulator needs gboolean to indicate EMISSION_STOP
|
||||
- accumulator needs data
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __G_CLOSURE_H__ */
|
187
gobject/genums.c
187
gobject/genums.c
@@ -30,14 +30,14 @@ static void g_enum_class_init (GEnumClass *class,
|
||||
gpointer class_data);
|
||||
static void g_flags_class_init (GFlagsClass *class,
|
||||
gpointer class_data);
|
||||
static void g_value_enum_init (GValue *value);
|
||||
static void g_value_enum_copy_value (const GValue *src_value,
|
||||
static void value_flags_enum_init (GValue *value);
|
||||
static void value_flags_enum_copy_value (const GValue *src_value,
|
||||
GValue *dest_value);
|
||||
static gchar* g_value_enum_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
static gchar* g_value_enum_lcopy_value (const GValue *value,
|
||||
static gchar* value_flags_enum_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
static gchar* value_flags_enum_lcopy_value (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
@@ -48,57 +48,106 @@ void
|
||||
g_enum_types_init (void) /* sync with gtype.c */
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
static const GTypeFundamentalInfo finfo = {
|
||||
G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE,
|
||||
static const GTypeValueTable flags_enum_value_table = {
|
||||
value_flags_enum_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_flags_enum_copy_value, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_INT, /* collect_type */
|
||||
value_flags_enum_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_flags_enum_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
static GTypeInfo info = {
|
||||
0 /* class_size */,
|
||||
NULL /* base_init */,
|
||||
NULL /* base_finalize */,
|
||||
NULL /* class_init */,
|
||||
NULL /* class_finalize */,
|
||||
NULL /* class_data */,
|
||||
0, /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_destroy */
|
||||
NULL, /* class_init */
|
||||
NULL, /* class_destroy */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
0, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
&flags_enum_value_table, /* value_table */
|
||||
};
|
||||
static const GTypeValueTable value_table = {
|
||||
g_value_enum_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
g_value_enum_copy_value, /* value_copy */
|
||||
G_VALUE_COLLECT_INT, /* collect_type */
|
||||
g_value_enum_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
g_value_enum_lcopy_value, /* lcopy_value */
|
||||
static const GTypeFundamentalInfo finfo = {
|
||||
G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE,
|
||||
};
|
||||
GType type;
|
||||
|
||||
g_return_if_fail (initialized == FALSE);
|
||||
initialized = TRUE;
|
||||
|
||||
info.value_table = &value_table;
|
||||
|
||||
|
||||
/* G_TYPE_ENUM
|
||||
*/
|
||||
info.class_size = sizeof (GEnumClass);
|
||||
type = g_type_register_fundamental (G_TYPE_ENUM, "GEnum", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_ENUM, "GEnum", &info, &finfo, G_TYPE_FLAG_ABSTRACT);
|
||||
g_assert (type == G_TYPE_ENUM);
|
||||
|
||||
/* G_TYPE_FLAGS
|
||||
*/
|
||||
info.class_size = sizeof (GFlagsClass);
|
||||
type = g_type_register_fundamental (G_TYPE_FLAGS, "GFlags", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_FLAGS, "GFlags", &info, &finfo, G_TYPE_FLAG_ABSTRACT);
|
||||
g_assert (type == G_TYPE_FLAGS);
|
||||
}
|
||||
|
||||
static void
|
||||
value_flags_enum_init (GValue *value)
|
||||
{
|
||||
value->data[0].v_long = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
value_flags_enum_copy_value (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
{
|
||||
dest_value->data[0].v_long = src_value->data[0].v_long;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
value_flags_enum_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
value->data[0].v_long = collect_value->v_int;
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
value_flags_enum_lcopy_value (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
gint *int_p = collect_value->v_pointer;
|
||||
|
||||
if (!int_p)
|
||||
return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
|
||||
|
||||
*int_p = value->data[0].v_long;
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GType
|
||||
g_enum_register_static (const gchar *name,
|
||||
const GEnumValue *const_static_values)
|
||||
{
|
||||
GTypeInfo enum_type_info = {
|
||||
sizeof (GEnumClass),
|
||||
NULL /* base_init */,
|
||||
NULL /* base_finalize */,
|
||||
sizeof (GEnumClass), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) g_enum_class_init,
|
||||
NULL /* class_finalize */,
|
||||
NULL /* class_data */,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
0, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
NULL, /* value_table */
|
||||
};
|
||||
GType type;
|
||||
|
||||
@@ -107,7 +156,7 @@ g_enum_register_static (const gchar *name,
|
||||
|
||||
enum_type_info.class_data = const_static_values;
|
||||
|
||||
type = g_type_register_static (G_TYPE_ENUM, name, &enum_type_info);
|
||||
type = g_type_register_static (G_TYPE_ENUM, name, &enum_type_info, 0);
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -117,12 +166,16 @@ g_flags_register_static (const gchar *name,
|
||||
const GFlagsValue *const_static_values)
|
||||
{
|
||||
GTypeInfo flags_type_info = {
|
||||
sizeof (GFlagsClass),
|
||||
NULL /* base_init */,
|
||||
NULL /* base_finalize */,
|
||||
sizeof (GFlagsClass), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) g_flags_class_init,
|
||||
NULL /* class_finalize */,
|
||||
NULL /* class_data */,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
0, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
NULL, /* value_table */
|
||||
};
|
||||
GType type;
|
||||
|
||||
@@ -131,7 +184,7 @@ g_flags_register_static (const gchar *name,
|
||||
|
||||
flags_type_info.class_data = const_static_values;
|
||||
|
||||
type = g_type_register_static (G_TYPE_FLAGS, name, &flags_type_info);
|
||||
type = g_type_register_static (G_TYPE_FLAGS, name, &flags_type_info, 0);
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -335,15 +388,15 @@ g_value_set_enum (GValue *value,
|
||||
gint v_enum)
|
||||
{
|
||||
g_return_if_fail (G_IS_VALUE_ENUM (value));
|
||||
|
||||
|
||||
value->data[0].v_long = v_enum;
|
||||
}
|
||||
|
||||
gint
|
||||
g_value_get_enum (GValue *value)
|
||||
g_value_get_enum (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_ENUM (value), 0);
|
||||
|
||||
|
||||
return value->data[0].v_long;
|
||||
}
|
||||
|
||||
@@ -352,56 +405,14 @@ g_value_set_flags (GValue *value,
|
||||
guint v_flags)
|
||||
{
|
||||
g_return_if_fail (G_IS_VALUE_FLAGS (value));
|
||||
|
||||
|
||||
value->data[0].v_ulong = v_flags;
|
||||
}
|
||||
|
||||
guint
|
||||
g_value_get_flags (GValue *value)
|
||||
g_value_get_flags (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_FLAGS (value), 0);
|
||||
|
||||
|
||||
return value->data[0].v_ulong;
|
||||
}
|
||||
|
||||
static void
|
||||
g_value_enum_init (GValue *value)
|
||||
{
|
||||
value->data[0].v_long = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
g_value_enum_copy_value (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
{
|
||||
dest_value->data[0].v_long = src_value->data[0].v_long;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
g_value_enum_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
value->data[0].v_long = collect_value->v_int;
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
g_value_enum_lcopy_value (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
gint *int_p = collect_value->v_pointer;
|
||||
|
||||
if (!int_p)
|
||||
return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
|
||||
|
||||
*int_p = value->data[0].v_long;
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -38,8 +38,8 @@ extern "C" {
|
||||
#define G_IS_FLAGS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_FLAGS))
|
||||
#define G_FLAGS_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
|
||||
#define G_FLAGS_CLASS_TYPE_NAME(class) (g_type_name (G_FLAGS_TYPE (class)))
|
||||
#define G_IS_VALUE_ENUM(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_ENUM))
|
||||
#define G_IS_VALUE_FLAGS(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_FLAGS))
|
||||
#define G_IS_VALUE_ENUM(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_ENUM))
|
||||
#define G_IS_VALUE_FLAGS(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_FLAGS))
|
||||
|
||||
|
||||
/* --- enum/flag values & classes --- */
|
||||
@@ -93,10 +93,10 @@ GFlagsValue* g_flags_get_value_by_nick (GFlagsClass *flags_class,
|
||||
const gchar *nick);
|
||||
void g_value_set_enum (GValue *value,
|
||||
gint v_enum);
|
||||
gint g_value_get_enum (GValue *value);
|
||||
gint g_value_get_enum (const GValue *value);
|
||||
void g_value_set_flags (GValue *value,
|
||||
guint v_flags);
|
||||
guint g_value_get_flags (GValue *value);
|
||||
guint g_value_get_flags (const GValue *value);
|
||||
|
||||
|
||||
|
||||
|
196
gobject/glib-genmarshal.1
Normal file
196
gobject/glib-genmarshal.1
Normal file
@@ -0,0 +1,196 @@
|
||||
.TH GLIB-GENMARSHAL 1 "18 Oct 2000"
|
||||
.SH NAME
|
||||
glib-genmarshal \- C code marshaller generation utility for GLib closures
|
||||
.SH SYNOPSIS
|
||||
|
||||
\fBglib-genmarshal\fP [\fIoptions\fP] [\fIfiles...\fP]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBglib-genmarshal\fP is a small utility that generates C code marshallers
|
||||
for callback functions of the GClosure mechanism in the GObject sublibrary
|
||||
of GLib. The marshaller functions have a standard signature, they get passed
|
||||
in the invoking closure, an array of value structures holding the callback
|
||||
function parameters and a value structure for the return value of the
|
||||
callback. The marshaller is then responsible to call the respective C code
|
||||
function of the closure with all the parameters on the stack and to collect
|
||||
its return value.
|
||||
|
||||
.SH INVOCATION
|
||||
|
||||
\fBglib-genmarshal\fP takes a list of marshallers to generate as input.
|
||||
The marshaller list is either read from standard input or from files
|
||||
passed as additional arguments on the command line.
|
||||
|
||||
.SS Options
|
||||
.TP
|
||||
\fI--header
|
||||
Generate header file contents of the marshallers.
|
||||
.TP
|
||||
\fI--body
|
||||
Generate C code file contents of the marshallers.
|
||||
.TP
|
||||
\fI--prefix=string, --prefix string
|
||||
Specify marshaller prefix. The default prefix is `\fIg_cclosure_marshal\fP'.
|
||||
.TP
|
||||
\fI--skip-source
|
||||
Skip source location remarks in generated comments.
|
||||
.TP
|
||||
\fI--g-fatal-warnings
|
||||
Make warnings fatal, that is, exit immediately once a warning occours.
|
||||
.TP
|
||||
\fI-h, --help\fP
|
||||
Print brief help and exit.
|
||||
.TP
|
||||
\fI-v, --version\fP
|
||||
Print version and exit.
|
||||
.PP
|
||||
|
||||
.SS Marshaller list format
|
||||
.PP
|
||||
The marshaller lists are processed line by line, a line can contain a
|
||||
comment in the form of
|
||||
.RS
|
||||
.PP
|
||||
# this is a comment
|
||||
.PP
|
||||
.RE
|
||||
or a marshaller specification of the form
|
||||
.RS
|
||||
.PP
|
||||
\fIRTYPE\fP:\fBPTYPE\fP
|
||||
.PP
|
||||
\fIRTYPE\fP:\fBPTYPE\fP,\fBPTYPE\fP
|
||||
.PP
|
||||
\fIRTYPE\fP:\fBPTYPE\fP,\fBPTYPE\fP,\fBPTYPE\fP
|
||||
.PP
|
||||
# up to 16 \fBPTYPE\fPs may be present
|
||||
.PP
|
||||
.RE
|
||||
The \fIRTYPE\fP part specifies the callback's return type and
|
||||
the \fBPTYPE\fPs right to the colon specify the callback's
|
||||
parameter list, except for the first and the last arguments which
|
||||
are always pointers.
|
||||
.PP
|
||||
|
||||
.SS Parameter types
|
||||
Currently, the following types are supported:
|
||||
.TP 12
|
||||
\fIVOID
|
||||
indicates no return type, or no extra parameters. if \fIVOID\fP is used as
|
||||
the parameter list, no additional parameters may be present.
|
||||
.TP 12
|
||||
\fIBOOLEAN
|
||||
for boolean types (gboolean)
|
||||
.TP 12
|
||||
\fICHAR
|
||||
for signed char types (gchar)
|
||||
.TP 12
|
||||
\fIUCHAR
|
||||
for unsigned char types (guchar)
|
||||
.TP 12
|
||||
\fIINT
|
||||
for signed integer types (gint)
|
||||
.TP 12
|
||||
\fIUINT
|
||||
for unsigned integer types (guint)
|
||||
.TP 12
|
||||
\fILONG
|
||||
for signed long integer types (glong)
|
||||
.TP 12
|
||||
\fIULONG
|
||||
for unsigned long integer types (gulong)
|
||||
.TP 12
|
||||
\fIENUM
|
||||
for enumeration types (gint)
|
||||
.TP 12
|
||||
\fIFLAGS
|
||||
for flag enumeration types (guint)
|
||||
.TP 12
|
||||
\fIFLOAT
|
||||
for single-precision float types (gfloat)
|
||||
.TP 12
|
||||
\fIDOUBLE
|
||||
for double-precision float types (gdouble)
|
||||
.TP 12
|
||||
\fISTRING
|
||||
for string types (gchar*)
|
||||
.TP 12
|
||||
\fIBOXED
|
||||
for boxed (anonymous but reference counted) types (GBoxed*)
|
||||
.TP 12
|
||||
\fIPOINTER
|
||||
for anonymous pointer types (gpointer)
|
||||
.TP 12
|
||||
\fIOBJECT
|
||||
for GObject or derived types (GObject*)
|
||||
.TP 12
|
||||
\fINONE
|
||||
deprecated alias for \fIVOID\fP
|
||||
.TP 12
|
||||
\fIBOOL
|
||||
deprecated alias for \fIBOOLEAN\fP
|
||||
|
||||
.SH EXAMPLE
|
||||
To generate marshallers for the following callback functions:
|
||||
.PP
|
||||
.RS
|
||||
.nf
|
||||
void foo (gpointer data1,
|
||||
gpointer data2);
|
||||
void bar (gpointer data1,
|
||||
gint param1,
|
||||
gpointer data2);
|
||||
gfloat baz (gpointer data1,
|
||||
gboolean param1,
|
||||
guchar param2,
|
||||
gpointer data2);
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
The marshaller list has to look like this:
|
||||
.PP
|
||||
.RS
|
||||
.nf
|
||||
VOID:VOID
|
||||
VOID:INT
|
||||
FLOAT:BOOLEAN,UCHAR
|
||||
.fi
|
||||
.RE
|
||||
.PP
|
||||
The generated marshallers have the arguments encoded
|
||||
in their function name. For this particular list, they
|
||||
are
|
||||
g_cclosure_marshal_VOID__VOID(),
|
||||
g_cclosure_marshal_VOID__INT(),
|
||||
g_cclosure_marshal_FLOAT__BOOLEAN_UCHAR().
|
||||
.PP
|
||||
They can be used directly for GClosures or be passed in as
|
||||
the GSignalCMarshaller c_marshaller; argument upon creation
|
||||
of signals:
|
||||
.PP
|
||||
.nf
|
||||
GClosure *cc_foo, *cc_bar, *cc_baz;
|
||||
|
||||
cc_foo = g_cclosure_new (NULL, foo, NULL);
|
||||
g_closure_set_marshal (cc_foo, g_cclosure_marshal_VOID__VOID);
|
||||
cc_bar = g_cclosure_new (NULL, bar, NULL);
|
||||
g_closure_set_marshal (cc_bar, g_cclosure_marshal_VOID__INT);
|
||||
cc_baz = g_cclosure_new (NULL, baz, NULL);
|
||||
g_closure_set_marshal (cc_baz, g_cclosure_marshal_FLOAT__BOOLEAN_UCHAR);
|
||||
.fi
|
||||
.PP
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
\fB
|
||||
glib-config(1)
|
||||
\fP
|
||||
|
||||
.SH BUGS
|
||||
None known yet.
|
||||
|
||||
.SH AUTHOR
|
||||
.B glib-genmarshal
|
||||
has been written by Tim Janik <timj@gtk.org>.
|
||||
.PP
|
||||
This manual page was provided by Tim Janik <timj@gtk.org>.
|
693
gobject/glib-genmarshal.c
Normal file
693
gobject/glib-genmarshal.c
Normal file
@@ -0,0 +1,693 @@
|
||||
/* GLIB-GenMarshal - Marshaller generator for GObject library
|
||||
* Copyright (C) 2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/* --- defines --- */
|
||||
#define PRG_NAME "glib-genmarshal"
|
||||
#define PKG_NAME "GLib"
|
||||
#define PKG_HTTP_HOME "http://www.gtk.org"
|
||||
|
||||
|
||||
/* --- typedefs & structures --- */
|
||||
typedef struct _Argument Argument;
|
||||
typedef struct _Signature Signature;
|
||||
struct _Argument
|
||||
{
|
||||
gchar *pname; /* parsed name */
|
||||
const gchar *sname; /* signature name */
|
||||
const gchar *func; /* functional extension */
|
||||
const gchar *cname; /* C name */
|
||||
};
|
||||
struct _Signature
|
||||
{
|
||||
gchar *ploc;
|
||||
Argument *rarg;
|
||||
GList *args; /* of type Argument* */
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
static void parse_args (gint *argc_p,
|
||||
gchar ***argv_p);
|
||||
static void print_blurb (FILE *bout,
|
||||
gboolean print_help);
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
static FILE *fout = NULL;
|
||||
static GScannerConfig scanner_config_template =
|
||||
{
|
||||
(
|
||||
" \t\r" /* "\n" is statement delimiter */
|
||||
) /* cset_skip_characters */,
|
||||
(
|
||||
G_CSET_a_2_z
|
||||
"_"
|
||||
G_CSET_A_2_Z
|
||||
) /* cset_identifier_first */,
|
||||
(
|
||||
G_CSET_a_2_z
|
||||
"_0123456789"
|
||||
G_CSET_A_2_Z
|
||||
) /* cset_identifier_nth */,
|
||||
( "#\n" ) /* cpair_comment_single */,
|
||||
|
||||
FALSE /* case_sensitive */,
|
||||
|
||||
TRUE /* skip_comment_multi */,
|
||||
TRUE /* skip_comment_single */,
|
||||
TRUE /* scan_comment_multi */,
|
||||
TRUE /* scan_identifier */,
|
||||
FALSE /* scan_identifier_1char */,
|
||||
FALSE /* scan_identifier_NULL */,
|
||||
TRUE /* scan_symbols */,
|
||||
FALSE /* scan_binary */,
|
||||
TRUE /* scan_octal */,
|
||||
TRUE /* scan_float */,
|
||||
TRUE /* scan_hex */,
|
||||
FALSE /* scan_hex_dollar */,
|
||||
TRUE /* scan_string_sq */,
|
||||
TRUE /* scan_string_dq */,
|
||||
TRUE /* numbers_2_int */,
|
||||
FALSE /* int_2_float */,
|
||||
FALSE /* identifier_2_string */,
|
||||
TRUE /* char_2_token */,
|
||||
FALSE /* symbol_2_token */,
|
||||
FALSE /* scope_0_fallback */,
|
||||
};
|
||||
static gchar *marshaller_prefix = "g_cclosure_marshal";
|
||||
static GHashTable *marshallers = NULL;
|
||||
static gboolean gen_cheader = FALSE;
|
||||
static gboolean gen_cbody = FALSE;
|
||||
static gboolean skip_ploc = FALSE;
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
static gboolean
|
||||
complete_arg (Argument *arg,
|
||||
gboolean is_return)
|
||||
{
|
||||
static const Argument inout_arguments[] = {
|
||||
/* pname, sname, func, cname */
|
||||
{ "VOID", "VOID", NULL, "void", },
|
||||
{ "BOOLEAN", "BOOLEAN", "boolean", "gboolean", },
|
||||
{ "CHAR", "CHAR", "char", "gchar", },
|
||||
{ "UCHAR", "UCHAR", "uchar", "guchar", },
|
||||
{ "INT", "INT", "int", "gint", },
|
||||
{ "UINT", "UINT", "uint", "guint", },
|
||||
{ "LONG", "LONG", "long", "glong", },
|
||||
{ "ULONG", "ULONG", "ulong", "gulong", },
|
||||
{ "ENUM", "ENUM", "enum", "gint", },
|
||||
{ "FLAGS", "FLAGS", "flags", "guint", },
|
||||
{ "FLOAT", "FLOAT", "float", "gfloat", },
|
||||
{ "DOUBLE", "DOUBLE", "double", "gdouble", },
|
||||
/* deprecated: */
|
||||
{ "NONE", "VOID", NULL, "void", },
|
||||
{ "BOOL", "BOOLEAN", "boolean", "gboolean", },
|
||||
};
|
||||
static const Argument in_arguments[] = {
|
||||
{ "STRING", "POINTER", "as_pointer", "gpointer", },
|
||||
{ "BOXED", "POINTER", "as_pointer", "gpointer", },
|
||||
{ "POINTER", "POINTER", "as_pointer", "gpointer", },
|
||||
{ "OBJECT", "POINTER", "as_pointer", "gpointer", },
|
||||
};
|
||||
static const Argument out_arguments[] = {
|
||||
{ "STRING", "STRING", "string", "gchar*", },
|
||||
{ "BOXED", "BOXED", "boxed", "gpointer", },
|
||||
{ "POINTER", "POINTER", "pointer", "gpointer", },
|
||||
{ "OBJECT", "OBJECT", "object", "GObject*", },
|
||||
};
|
||||
const guint n_inout_arguments = sizeof (inout_arguments) / sizeof (inout_arguments[0]);
|
||||
const guint n_out_arguments = sizeof (out_arguments) / sizeof (out_arguments[0]);
|
||||
const guint n_in_arguments = sizeof (in_arguments) / sizeof (in_arguments[0]);
|
||||
const Argument *arguments;
|
||||
guint i, n_arguments;
|
||||
|
||||
g_return_val_if_fail (arg != NULL, FALSE);
|
||||
|
||||
arguments = inout_arguments;
|
||||
n_arguments = n_inout_arguments;
|
||||
for (i = 0; i < n_arguments; i++)
|
||||
if (strcmp (arguments[i].pname, arg->pname) == 0)
|
||||
{
|
||||
arg->sname = arguments[i].sname;
|
||||
arg->func = arguments[i].func;
|
||||
arg->cname = arguments[i].cname;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
arguments = is_return ? out_arguments : in_arguments;
|
||||
n_arguments = is_return ? n_out_arguments : n_in_arguments;
|
||||
for (i = 0; i < n_arguments; i++)
|
||||
if (strcmp (arguments[i].pname, arg->pname) == 0)
|
||||
{
|
||||
arg->sname = arguments[i].sname;
|
||||
arg->func = arguments[i].func;
|
||||
arg->cname = arguments[i].cname;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
pad (const gchar *string)
|
||||
{
|
||||
#define PAD_LENGTH 12
|
||||
static gchar *buffer = NULL;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
if (!buffer)
|
||||
buffer = g_new (gchar, PAD_LENGTH + 1);
|
||||
|
||||
/* paranoid check */
|
||||
if (strlen (string) >= PAD_LENGTH)
|
||||
{
|
||||
g_free (buffer);
|
||||
buffer = g_strdup_printf ("%s ", string);
|
||||
g_warning ("overfull string (%u bytes) for padspace", strlen (string));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
for (i = 0; i < PAD_LENGTH; i++)
|
||||
{
|
||||
gboolean done = *string == 0;
|
||||
|
||||
buffer[i] = done ? ' ' : *string++;
|
||||
}
|
||||
buffer[i] = 0;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
indent (guint n_spaces)
|
||||
{
|
||||
static gchar *buffer;
|
||||
static guint blength = 0;
|
||||
|
||||
if (blength <= n_spaces)
|
||||
{
|
||||
blength = n_spaces + 1;
|
||||
g_free (buffer);
|
||||
buffer = g_new (gchar, blength);
|
||||
}
|
||||
memset (buffer, ' ', n_spaces);
|
||||
buffer[n_spaces] = 0;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
generate_marshal (const gchar *signame,
|
||||
Signature *sig)
|
||||
{
|
||||
guint ind, a;
|
||||
GList *node;
|
||||
|
||||
if (g_hash_table_lookup (marshallers, signame))
|
||||
return;
|
||||
else
|
||||
{
|
||||
gchar *tmp = g_strdup (signame);
|
||||
|
||||
g_hash_table_insert (marshallers, tmp, tmp);
|
||||
}
|
||||
|
||||
if (gen_cheader)
|
||||
{
|
||||
ind = fprintf (fout, "extern void ");
|
||||
ind += fprintf (fout, "%s_%s (", marshaller_prefix, signame);
|
||||
fprintf (fout, "GClosure *closure,\n");
|
||||
fprintf (fout, "%sguint invocation_hint,\n", indent (ind));
|
||||
fprintf (fout, "%sGValue *return_value,\n", indent (ind));
|
||||
fprintf (fout, "%sguint n_param_values,\n", indent (ind));
|
||||
fprintf (fout, "%sconst GValue *param_values,\n", indent (ind));
|
||||
fprintf (fout, "%sgpointer marshal_data);\n", indent (ind));
|
||||
}
|
||||
if (gen_cbody)
|
||||
{
|
||||
/* cfile marhsal header */
|
||||
fprintf (fout, "void\n");
|
||||
ind = fprintf (fout, "%s_%s (", marshaller_prefix, signame);
|
||||
fprintf (fout, "GClosure *closure,\n");
|
||||
fprintf (fout, "%sguint invocation_hint,\n", indent (ind));
|
||||
fprintf (fout, "%sGValue *return_value,\n", indent (ind));
|
||||
fprintf (fout, "%sguint n_param_values,\n", indent (ind));
|
||||
fprintf (fout, "%sconst GValue *param_values,\n", indent (ind));
|
||||
fprintf (fout, "%sgpointer marshal_data)\n", indent (ind));
|
||||
fprintf (fout, "{\n");
|
||||
|
||||
/* cfile GSignalFunc typedef */
|
||||
ind = fprintf (fout, " typedef %s (*GSignalFunc_%s) (", sig->rarg->cname, signame);
|
||||
fprintf (fout, "%s data1,\n", pad ("gpointer"));
|
||||
for (a = 1, node = sig->args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
|
||||
if (arg->func)
|
||||
fprintf (fout, "%s%s arg_%d,\n", indent (ind), pad (arg->cname), a++);
|
||||
}
|
||||
fprintf (fout, "%s%s data2);\n", indent (ind), pad ("gpointer"));
|
||||
|
||||
/* cfile marshal variables */
|
||||
fprintf (fout, " register GSignalFunc_%s callback;\n", signame);
|
||||
fprintf (fout, " register GCClosure *cc = (GCClosure*) closure;\n");
|
||||
fprintf (fout, " register gpointer data1, data2;\n");
|
||||
if (sig->rarg->func)
|
||||
fprintf (fout, " %s v_return;\n", sig->rarg->cname);
|
||||
|
||||
if (sig->args || sig->rarg->func)
|
||||
{
|
||||
fprintf (fout, "\n");
|
||||
|
||||
if (sig->rarg->func)
|
||||
fprintf (fout, " g_return_if_fail (return_value != NULL);\n");
|
||||
if (sig->args)
|
||||
{
|
||||
for (a = 0, node = sig->args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
|
||||
if (arg->func)
|
||||
a++;
|
||||
}
|
||||
fprintf (fout, " g_return_if_fail (n_param_values >= %u);\n", 1 + a);
|
||||
}
|
||||
}
|
||||
|
||||
/* cfile marshal data1, data2 and callback setup */
|
||||
fprintf (fout, "\n");
|
||||
fprintf (fout, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
|
||||
fprintf (fout, " data1 = closure->data;\n");
|
||||
fprintf (fout, " data2 = g_value_get_as_pointer (param_values + 0);\n");
|
||||
fprintf (fout, " }\n else\n {\n");
|
||||
fprintf (fout, " data1 = g_value_get_as_pointer (param_values + 0);\n");
|
||||
fprintf (fout, " data2 = closure->data;\n");
|
||||
fprintf (fout, " }\n");
|
||||
fprintf (fout, " callback = (GSignalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame);
|
||||
|
||||
/* cfile marshal callback action */
|
||||
fprintf (fout, "\n");
|
||||
ind = fprintf (fout, " %s callback (", sig->rarg->func ? " v_return =" : "");
|
||||
fprintf (fout, "data1,\n");
|
||||
for (a = 1, node = sig->args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
|
||||
if (arg->func)
|
||||
fprintf (fout, "%sg_value_get_%s (param_values + %d),\n", indent (ind), arg->func, a++);
|
||||
}
|
||||
fprintf (fout, "%sdata2);\n", indent (ind));
|
||||
|
||||
/* cfile marshal return value storage */
|
||||
if (sig->rarg->func)
|
||||
{
|
||||
fprintf (fout, "\n");
|
||||
fprintf (fout, " g_value_set_%s (return_value, v_return);\n", sig->rarg->func);
|
||||
}
|
||||
|
||||
/* cfile marshal footer */
|
||||
fprintf (fout, "}\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_signature (Signature *sig)
|
||||
{
|
||||
gchar *pname, *sname;
|
||||
GList *node;
|
||||
|
||||
/* lookup and complete info on arguments */
|
||||
if (!complete_arg (sig->rarg, TRUE))
|
||||
{
|
||||
g_warning ("unknown type: %s", sig->rarg->pname);
|
||||
return;
|
||||
}
|
||||
for (node = sig->args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
|
||||
if (!complete_arg (arg, FALSE))
|
||||
{
|
||||
g_warning ("unknown type: %s", arg->pname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* construct requested marshaller name and technical marshaller name */
|
||||
pname = g_strconcat (sig->rarg->pname, "_", NULL);
|
||||
sname = g_strconcat (sig->rarg->sname, "_", NULL);
|
||||
for (node = sig->args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
gchar *tmp;
|
||||
|
||||
tmp = sname;
|
||||
sname = g_strconcat (tmp, "_", arg->sname, NULL);
|
||||
g_free (tmp);
|
||||
tmp = pname;
|
||||
pname = g_strconcat (tmp, "_", arg->pname, NULL);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
/* introductionary comment */
|
||||
fprintf (fout, "\n/* %s", sig->rarg->pname);
|
||||
for (node = sig->args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
|
||||
fprintf (fout, "%c%s", node->prev ? ',' : ':', arg->pname);
|
||||
}
|
||||
if (!skip_ploc)
|
||||
fprintf (fout, " (%s)", sig->ploc);
|
||||
fprintf (fout, " */\n");
|
||||
|
||||
/* generate signature marshaller */
|
||||
generate_marshal (sname, sig);
|
||||
|
||||
/* put out marshaler alias if required */
|
||||
if (gen_cheader && !g_hash_table_lookup (marshallers, pname))
|
||||
{
|
||||
gchar *tmp = g_strdup (pname);
|
||||
|
||||
fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, pname, marshaller_prefix, sname);
|
||||
|
||||
g_hash_table_insert (marshallers, tmp, tmp);
|
||||
}
|
||||
|
||||
g_free (pname);
|
||||
g_free (sname);
|
||||
}
|
||||
|
||||
static Argument*
|
||||
new_arg (const gchar *pname)
|
||||
{
|
||||
Argument *arg = g_new0 (Argument, 1);
|
||||
|
||||
arg->pname = g_strdup (pname);
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
static guint
|
||||
parse_line (GScanner *scanner,
|
||||
Signature *sig)
|
||||
{
|
||||
/* parse identifier for return value */
|
||||
if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER)
|
||||
return G_TOKEN_IDENTIFIER;
|
||||
sig->rarg = new_arg (scanner->value.v_identifier);
|
||||
|
||||
/* keep a note on the location */
|
||||
sig->ploc = g_strdup_printf ("%s:%u", scanner->input_name, scanner->line);
|
||||
|
||||
/* expect ':' */
|
||||
if (g_scanner_get_next_token (scanner) != ':')
|
||||
return ':';
|
||||
|
||||
/* parse first argument */
|
||||
if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER)
|
||||
return G_TOKEN_IDENTIFIER;
|
||||
sig->args = g_list_append (sig->args, new_arg (scanner->value.v_identifier));
|
||||
|
||||
/* parse rest of argument list */
|
||||
while (g_scanner_peek_next_token (scanner) == ',')
|
||||
{
|
||||
/* eat comma */
|
||||
g_scanner_get_next_token (scanner);
|
||||
|
||||
/* parse arg identifier */
|
||||
if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER)
|
||||
return G_TOKEN_IDENTIFIER;
|
||||
sig->args = g_list_append (sig->args, new_arg (scanner->value.v_identifier));
|
||||
}
|
||||
|
||||
/* expect end of line, done */
|
||||
if (g_scanner_get_next_token (scanner) != '\n')
|
||||
return '\n';
|
||||
|
||||
/* success */
|
||||
return G_TOKEN_NONE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
string_key_destroy (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_free (key);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
GScanner *scanner;
|
||||
GSList *slist, *files = NULL;
|
||||
gint i;
|
||||
|
||||
/* parse args and do fast exits */
|
||||
parse_args (&argc, &argv);
|
||||
|
||||
/* list input files */
|
||||
for (i = 1; i < argc; i++)
|
||||
files = g_slist_prepend (files, argv[i]);
|
||||
if (files)
|
||||
files = g_slist_reverse (files);
|
||||
else
|
||||
files = g_slist_prepend (files, "/dev/stdin");
|
||||
|
||||
/* setup auxillary structs */
|
||||
scanner = g_scanner_new (&scanner_config_template);
|
||||
fout = stdout;
|
||||
marshallers = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
/* process input files */
|
||||
for (slist = files; slist; slist = slist->next)
|
||||
{
|
||||
gchar *file = slist->data;
|
||||
gint fd = open (file, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
g_warning ("failed to open \"%s\": %s", file, g_strerror (errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* set file name for error reports */
|
||||
scanner->input_name = file;
|
||||
|
||||
/* parse & process file */
|
||||
g_scanner_input_file (scanner, fd);
|
||||
|
||||
/* scanning loop, we parse the input untill it's end is reached,
|
||||
* or our sub routine came across invalid syntax
|
||||
*/
|
||||
do
|
||||
{
|
||||
guint expected_token = G_TOKEN_NONE;
|
||||
|
||||
switch (g_scanner_peek_next_token (scanner))
|
||||
{
|
||||
case '\n':
|
||||
/* eat newline and restart */
|
||||
g_scanner_get_next_token (scanner);
|
||||
continue;
|
||||
case G_TOKEN_EOF:
|
||||
/* done */
|
||||
break;
|
||||
default:
|
||||
/* parse and process signatures */
|
||||
{
|
||||
Signature signature = { NULL, NULL, NULL };
|
||||
GList *node;
|
||||
|
||||
expected_token = parse_line (scanner, &signature);
|
||||
|
||||
/* once we got a valid signature, process it */
|
||||
if (expected_token == G_TOKEN_NONE)
|
||||
process_signature (&signature);
|
||||
|
||||
/* clean up signature contents */
|
||||
g_free (signature.ploc);
|
||||
if (signature.rarg)
|
||||
g_free (signature.rarg->pname);
|
||||
g_free (signature.rarg);
|
||||
for (node = signature.args; node; node = node->next)
|
||||
{
|
||||
Argument *arg = node->data;
|
||||
|
||||
g_free (arg->pname);
|
||||
g_free (arg);
|
||||
}
|
||||
g_list_free (signature.args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* bail out on errors */
|
||||
if (expected_token != G_TOKEN_NONE)
|
||||
{
|
||||
g_scanner_unexp_token (scanner, expected_token, "type name", NULL, NULL, NULL, TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
g_scanner_peek_next_token (scanner);
|
||||
}
|
||||
while (scanner->next_token != G_TOKEN_EOF);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
g_slist_free (files);
|
||||
g_scanner_destroy (scanner);
|
||||
g_hash_table_foreach_remove (marshallers, string_key_destroy, NULL);
|
||||
g_hash_table_destroy (marshallers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_args (gint *argc_p,
|
||||
gchar ***argv_p)
|
||||
{
|
||||
guint argc = *argc_p;
|
||||
gchar **argv = *argv_p;
|
||||
guint i, e;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp ("--header", argv[i]) == 0)
|
||||
{
|
||||
gen_cheader = TRUE;
|
||||
argv[i] = NULL;
|
||||
}
|
||||
else if (strcmp ("--body", argv[i]) == 0)
|
||||
{
|
||||
gen_cbody = TRUE;
|
||||
argv[i] = NULL;
|
||||
}
|
||||
else if (strcmp ("--skip-source", argv[i]) == 0)
|
||||
{
|
||||
skip_ploc = TRUE;
|
||||
argv[i] = NULL;
|
||||
}
|
||||
else if ((strcmp ("--prefix", argv[i]) == 0) ||
|
||||
(strncmp ("--prefix=", argv[i], 9) == 0))
|
||||
{
|
||||
gchar *equal = argv[i] + 8;
|
||||
|
||||
if (*equal == '=')
|
||||
marshaller_prefix = g_strdup (equal + 1);
|
||||
else if (i + 1 < argc)
|
||||
{
|
||||
marshaller_prefix = g_strdup (argv[i + 1]);
|
||||
argv[i] = NULL;
|
||||
i += 1;
|
||||
}
|
||||
argv[i] = NULL;
|
||||
}
|
||||
else if (strcmp ("-h", argv[i]) == 0 ||
|
||||
strcmp ("--help", argv[i]) == 0)
|
||||
{
|
||||
print_blurb (stderr, TRUE);
|
||||
argv[i] = NULL;
|
||||
exit (0);
|
||||
}
|
||||
else if (strcmp ("-v", argv[i]) == 0 ||
|
||||
strcmp ("--version", argv[i]) == 0)
|
||||
{
|
||||
print_blurb (stderr, FALSE);
|
||||
argv[i] = NULL;
|
||||
exit (0);
|
||||
}
|
||||
else if (strcmp (argv[i], "--g-fatal-warnings") == 0)
|
||||
{
|
||||
GLogLevelFlags fatal_mask;
|
||||
|
||||
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
|
||||
g_log_set_always_fatal (fatal_mask);
|
||||
|
||||
argv[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
e = 0;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
if (argv[i])
|
||||
{
|
||||
argv[e++] = argv[i];
|
||||
argv[i] = NULL;
|
||||
}
|
||||
}
|
||||
else if (!argv[i])
|
||||
e = i;
|
||||
}
|
||||
if (e)
|
||||
*argc_p = e;
|
||||
}
|
||||
|
||||
static void
|
||||
print_blurb (FILE *bout,
|
||||
gboolean print_help)
|
||||
{
|
||||
if (!print_help)
|
||||
{
|
||||
fprintf (bout, "%s version ", PRG_NAME);
|
||||
fprintf (bout, "%u.%u.%u", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
|
||||
fprintf (bout, "\n");
|
||||
fprintf (bout, "%s comes with ABSOLUTELY NO WARRANTY.\n", PRG_NAME);
|
||||
fprintf (bout, "You may redistribute copies of %s under the terms of\n", PRG_NAME);
|
||||
fprintf (bout, "the GNU General Public License which can be found in the\n");
|
||||
fprintf (bout, "%s source package. Sources, examples and contact\n", PKG_NAME);
|
||||
fprintf (bout, "information are available at %s\n", PKG_HTTP_HOME);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (bout, "Usage: %s [options] [files...]\n", PRG_NAME);
|
||||
fprintf (bout, " --header generate C headers\n");
|
||||
fprintf (bout, " --body generate C code\n");
|
||||
fprintf (bout, " --prefix=string specify marshaller prefix\n");
|
||||
fprintf (bout, " --skip-source skip source location comments\n");
|
||||
fprintf (bout, " -h, --help show this help message\n");
|
||||
fprintf (bout, " -v, --version print version informations\n");
|
||||
fprintf (bout, " --g-fatal-warnings make warnings fatal (abort)\n");
|
||||
}
|
||||
}
|
@@ -16,7 +16,7 @@
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "../config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
|
@@ -46,6 +46,7 @@ static void g_value_object_init (GValue *value);
|
||||
static void g_value_object_free_value (GValue *value);
|
||||
static void g_value_object_copy_value (const GValue *src_value,
|
||||
GValue *dest_value);
|
||||
static gpointer g_value_object_peek_pointer (const GValue *value);
|
||||
static gchar* g_value_object_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
@@ -59,6 +60,7 @@ static gchar* g_value_object_lcopy_value (const GValue *value,
|
||||
/* --- variables --- */
|
||||
static GQuark quark_param_id = 0;
|
||||
static GQuark quark_param_changed_queue = 0;
|
||||
static GQuark quark_closure_array = 0;
|
||||
static GHashTable *param_spec_hash_table = NULL;
|
||||
|
||||
|
||||
@@ -122,6 +124,7 @@ g_object_type_init (void) /* sync with gtype.c */
|
||||
g_value_object_init, /* value_init */
|
||||
g_value_object_free_value, /* value_free */
|
||||
g_value_object_copy_value, /* value_copy */
|
||||
g_value_object_peek_pointer, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_POINTER, /* collect_type */
|
||||
g_value_object_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
@@ -135,7 +138,7 @@ g_object_type_init (void) /* sync with gtype.c */
|
||||
/* G_TYPE_OBJECT
|
||||
*/
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_OBJECT);
|
||||
|
||||
#ifdef DEBUG_OBJECTS
|
||||
@@ -178,6 +181,7 @@ g_object_do_class_init (GObjectClass *class)
|
||||
{
|
||||
quark_param_id = g_quark_from_static_string ("glib-object-param-id");
|
||||
quark_param_changed_queue = g_quark_from_static_string ("glib-object-param-changed-queue");
|
||||
quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
|
||||
param_spec_hash_table = g_param_spec_hash_table_new ();
|
||||
|
||||
class->queue_param_changed = g_object_do_queue_param_changed;
|
||||
@@ -810,6 +814,12 @@ g_value_object_copy_value (const GValue *src_value,
|
||||
dest_value->data[0].v_pointer = NULL;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
g_value_object_peek_pointer (const GValue *value)
|
||||
{
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
g_value_object_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
@@ -874,7 +884,7 @@ g_value_set_object (GValue *value,
|
||||
}
|
||||
|
||||
GObject*
|
||||
g_value_get_object (GValue *value)
|
||||
g_value_get_object (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
|
||||
|
||||
@@ -882,9 +892,137 @@ g_value_get_object (GValue *value)
|
||||
}
|
||||
|
||||
GObject*
|
||||
g_value_dup_object (GValue *value)
|
||||
g_value_dup_object (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
|
||||
|
||||
return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GObject *object;
|
||||
guint n_closures;
|
||||
GClosure *closures[1]; /* flexible array */
|
||||
} CArray;
|
||||
|
||||
static void
|
||||
object_remove_closure (gpointer data,
|
||||
GClosure *closure)
|
||||
{
|
||||
GObject *object = data;
|
||||
CArray *carray = g_object_get_qdata (object, quark_closure_array);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < carray->n_closures; i++)
|
||||
if (carray->closures[i] == closure)
|
||||
{
|
||||
carray->n_closures--;
|
||||
if (i < carray->n_closures)
|
||||
carray->closures[i] = carray->closures[carray->n_closures];
|
||||
return;
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_closure_array (gpointer data)
|
||||
{
|
||||
CArray *carray = data;
|
||||
GObject *object = carray->object;
|
||||
guint i, n = carray->n_closures;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
GClosure *closure = carray->closures[i];
|
||||
|
||||
/* removing object_remove_closure() upfront is probably faster than
|
||||
* letting it fiddle with quark_closure_array which is empty anyways
|
||||
*/
|
||||
g_closure_remove_inotify (closure, object, object_remove_closure);
|
||||
g_closure_invalidate (closure);
|
||||
}
|
||||
g_free (carray);
|
||||
}
|
||||
|
||||
void
|
||||
g_object_watch_closure (GObject *object,
|
||||
GClosure *closure)
|
||||
{
|
||||
CArray *carray;
|
||||
|
||||
g_return_if_fail (G_IS_OBJECT (object));
|
||||
g_return_if_fail (closure != NULL);
|
||||
g_return_if_fail (closure->is_invalid == FALSE);
|
||||
g_return_if_fail (closure->in_marshal == FALSE);
|
||||
g_return_if_fail (object->ref_count > 0); /* this doesn't work on finalizing objects */
|
||||
|
||||
g_closure_add_inotify (closure, object, object_remove_closure);
|
||||
g_closure_add_marshal_guards (closure,
|
||||
object, (GClosureNotify) g_object_ref,
|
||||
object, (GClosureNotify) g_object_unref);
|
||||
carray = g_object_get_qdata (object, quark_closure_array);
|
||||
if (!carray)
|
||||
{
|
||||
carray = g_renew (CArray, NULL, 1);
|
||||
carray->object = object;
|
||||
carray->n_closures = 1;
|
||||
carray->closures[0] = closure;
|
||||
g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
|
||||
}
|
||||
else
|
||||
{
|
||||
guint i = carray->n_closures++;
|
||||
|
||||
carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
|
||||
carray->closures[i] = closure;
|
||||
}
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_closure_new_object (guint sizeof_closure,
|
||||
GObject *object)
|
||||
{
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||
g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
|
||||
|
||||
closure = g_closure_new_simple (sizeof_closure, object);
|
||||
g_object_watch_closure (object, closure);
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_cclosure_new_object (gpointer _object,
|
||||
GCallback callback_func)
|
||||
{
|
||||
GObject *object = _object;
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||
g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
|
||||
g_return_val_if_fail (callback_func != NULL, NULL);
|
||||
|
||||
closure = g_cclosure_new (callback_func, object, NULL);
|
||||
g_object_watch_closure (object, closure);
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
||||
GClosure*
|
||||
g_cclosure_new_object_swap (gpointer _object,
|
||||
GCallback callback_func)
|
||||
{
|
||||
GObject *object = _object;
|
||||
GClosure *closure;
|
||||
|
||||
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||
g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
|
||||
g_return_val_if_fail (callback_func != NULL, NULL);
|
||||
|
||||
closure = g_cclosure_new_swap (callback_func, object, NULL);
|
||||
g_object_watch_closure (object, closure);
|
||||
|
||||
return closure;
|
||||
}
|
||||
|
@@ -16,12 +16,13 @@
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __G_GOBJECT_H__
|
||||
#define __G_GOBJECT_H__
|
||||
#ifndef __G_OBJECT_H__
|
||||
#define __G_OBJECT_H__
|
||||
|
||||
#include <gobject/gtype.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gparam.h>
|
||||
#include <gobject/gclosure.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -31,38 +32,35 @@ extern "C" {
|
||||
|
||||
/* --- type macros --- */
|
||||
#define G_TYPE_IS_OBJECT(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT)
|
||||
#define G_OBJECT(object) (G_IS_OBJECT (object) ? ((GObject*) (object)) : \
|
||||
G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
|
||||
#define G_OBJECT_CLASS(class) (G_IS_OBJECT_CLASS (class) ? ((GObjectClass*) (class)) : \
|
||||
G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_OBJECT, GObjectClass))
|
||||
#define G_IS_OBJECT(object) (((GObject*) (object)) != NULL && \
|
||||
G_IS_OBJECT_CLASS (((GTypeInstance*) (object))->g_class))
|
||||
#define G_IS_OBJECT_CLASS(class) (((GTypeClass*) (class)) != NULL && \
|
||||
G_TYPE_IS_OBJECT (((GTypeClass*) (class))->g_type))
|
||||
#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
|
||||
#define G_OBJECT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_OBJECT, GObjectClass))
|
||||
#define G_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_OBJECT))
|
||||
#define G_IS_OBJECT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_OBJECT))
|
||||
#define G_OBJECT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), G_TYPE_OBJECT, GObjectClass))
|
||||
#define G_OBJECT_TYPE(object) (G_TYPE_FROM_INSTANCE (object))
|
||||
#define G_OBJECT_TYPE_NAME(object) (g_type_name (G_OBJECT_TYPE (object)))
|
||||
#define G_OBJECT_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
|
||||
#define G_OBJECT_CLASS_NAME(class) (g_type_name (G_OBJECT_CLASS_TYPE (class)))
|
||||
#define G_IS_VALUE_OBJECT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_OBJECT))
|
||||
#define G_IS_VALUE_OBJECT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_OBJECT))
|
||||
|
||||
#define G_NOTIFY_PRIORITY (G_PRIORITY_HIGH_IDLE + 20)
|
||||
|
||||
|
||||
/* --- typedefs & structures --- */
|
||||
typedef struct _GObject GObject;
|
||||
typedef struct _GObjectClass GObjectClass;
|
||||
typedef void (*GObjectGetParamFunc) (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec,
|
||||
const gchar *trailer);
|
||||
typedef void (*GObjectSetParamFunc) (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec,
|
||||
const gchar *trailer);
|
||||
typedef void (*GObjectFinalizeFunc) (GObject *object);
|
||||
typedef struct _GObject GObject;
|
||||
typedef struct _GObjectClass GObjectClass;
|
||||
typedef struct _GObjectConstructParam GObjectConstructParam;
|
||||
typedef void (*GObjectGetParamFunc) (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec,
|
||||
const gchar *trailer);
|
||||
typedef void (*GObjectSetParamFunc) (GObject *object,
|
||||
guint param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec,
|
||||
const gchar *trailer);
|
||||
typedef void (*GObjectFinalizeFunc) (GObject *object);
|
||||
struct _GObject
|
||||
{
|
||||
GTypeInstance g_type_instance;
|
||||
@@ -77,7 +75,10 @@ struct _GObjectClass
|
||||
|
||||
guint n_param_specs;
|
||||
GParamSpec **param_specs;
|
||||
|
||||
|
||||
GObject* (*constructor) (GType type, // FIXME!!!
|
||||
guint n_construct_params,
|
||||
GObjectConstructParam *construct_params);
|
||||
void (*get_param) (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
@@ -85,7 +86,7 @@ struct _GObjectClass
|
||||
const gchar *trailer);
|
||||
void (*set_param) (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec,
|
||||
const gchar *trailer);
|
||||
void (*queue_param_changed) (GObject *object,
|
||||
@@ -95,6 +96,12 @@ struct _GObjectClass
|
||||
void (*shutdown) (GObject *object);
|
||||
void (*finalize) (GObject *object);
|
||||
};
|
||||
struct _GObjectConstructParam
|
||||
{
|
||||
GParamSpec *pspec;
|
||||
GValue *value;
|
||||
gchar *trailer;
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
@@ -142,10 +149,18 @@ void g_object_set_qdata_full (GObject *object,
|
||||
GDestroyNotify destroy);
|
||||
gpointer g_object_steal_qdata (GObject *object,
|
||||
GQuark quark);
|
||||
void g_object_watch_closure (GObject *object,
|
||||
GClosure *closure);
|
||||
GClosure* g_cclosure_new_object (gpointer object,
|
||||
GCallback callback_func);
|
||||
GClosure* g_cclosure_new_object_swap (gpointer object,
|
||||
GCallback callback_func);
|
||||
GClosure* g_closure_new_object (guint sizeof_closure,
|
||||
GObject *object);
|
||||
void g_value_set_object (GValue *value,
|
||||
GObject *v_object);
|
||||
GObject* g_value_get_object (GValue *value);
|
||||
GObject* g_value_dup_object (GValue *value);
|
||||
GObject* g_value_get_object (const GValue *value);
|
||||
GObject* g_value_dup_object (const GValue *value);
|
||||
|
||||
|
||||
/* --- implementation macros --- */
|
||||
@@ -168,4 +183,4 @@ G_STMT_START { \
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __G_GOBJECT_H__ */
|
||||
#endif /* __G_OBJECT_H__ */
|
||||
|
@@ -63,7 +63,7 @@ g_param_type_init (void) /* sync with gtype.c */
|
||||
};
|
||||
GType type;
|
||||
|
||||
type = g_type_register_fundamental (G_TYPE_PARAM, "GParam", ¶m_spec_info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_PARAM, "GParam", ¶m_spec_info, &finfo, G_TYPE_FLAG_ABSTRACT);
|
||||
g_assert (type == G_TYPE_PARAM);
|
||||
}
|
||||
|
||||
@@ -380,3 +380,91 @@ g_param_spec_hash_table_lookup (GHashTable *hash_table,
|
||||
|
||||
return pspec;
|
||||
}
|
||||
|
||||
|
||||
/* --- auxillary functions --- */
|
||||
typedef struct
|
||||
{
|
||||
/* class portion */
|
||||
GType value_type;
|
||||
void (*finalize) (GParamSpec *pspec);
|
||||
void (*value_set_default) (GParamSpec *pspec,
|
||||
GValue *value);
|
||||
gboolean (*value_validate) (GParamSpec *pspec,
|
||||
GValue *value);
|
||||
gint (*values_cmp) (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2);
|
||||
} ParamSpecClassInfo;
|
||||
|
||||
static void
|
||||
param_spec_generic_class_init (gpointer g_class,
|
||||
gpointer class_data)
|
||||
{
|
||||
GParamSpecClass *class = g_class;
|
||||
ParamSpecClassInfo *info = class_data;
|
||||
|
||||
class->value_type = info->value_type;
|
||||
if (info->finalize)
|
||||
class->finalize = info->finalize; /* optional */
|
||||
class->value_set_default = info->value_set_default;
|
||||
if (info->value_validate)
|
||||
class->value_validate = info->value_validate; /* optional */
|
||||
class->values_cmp = info->values_cmp;
|
||||
g_free (class_data);
|
||||
}
|
||||
|
||||
static void
|
||||
default_value_set_default (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
/* value is already zero initialized */
|
||||
}
|
||||
|
||||
static gint
|
||||
default_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2)
|
||||
{
|
||||
return memcmp (&value1->data, &value2->data, sizeof (value1->data));
|
||||
}
|
||||
|
||||
GType
|
||||
g_param_type_register_static (const gchar *name,
|
||||
const GParamSpecTypeInfo *pspec_info)
|
||||
{
|
||||
GTypeInfo info = {
|
||||
sizeof (GParamSpecClass), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_destroy */
|
||||
param_spec_generic_class_init, /* class_init */
|
||||
NULL, /* class_destroy */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
};
|
||||
ParamSpecClassInfo *cinfo;
|
||||
|
||||
g_return_val_if_fail (name != NULL, 0);
|
||||
g_return_val_if_fail (pspec_info != NULL, 0);
|
||||
g_return_val_if_fail (g_type_from_name (name) == 0, 0);
|
||||
g_return_val_if_fail (pspec_info->instance_size >= sizeof (GParamSpec), 0);
|
||||
g_return_val_if_fail (g_type_name (pspec_info->value_type) != NULL, 0);
|
||||
/* default: g_return_val_if_fail (pspec_info->value_set_default != NULL, 0); */
|
||||
/* optional: g_return_val_if_fail (pspec_info->value_validate != NULL, 0); */
|
||||
/* default: g_return_val_if_fail (pspec_info->values_cmp != NULL, 0); */
|
||||
|
||||
info.instance_size = pspec_info->instance_size;
|
||||
info.n_preallocs = pspec_info->n_preallocs;
|
||||
info.instance_init = (GInstanceInitFunc) pspec_info->instance_init;
|
||||
cinfo = g_new (ParamSpecClassInfo, 1);
|
||||
cinfo->value_type = pspec_info->value_type;
|
||||
cinfo->finalize = pspec_info->finalize;
|
||||
cinfo->value_set_default = pspec_info->value_set_default ? pspec_info->value_set_default : default_value_set_default;
|
||||
cinfo->value_validate = pspec_info->value_validate;
|
||||
cinfo->values_cmp = pspec_info->values_cmp ? pspec_info->values_cmp : default_values_cmp;
|
||||
info.class_data = cinfo;
|
||||
|
||||
return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
|
||||
}
|
||||
|
@@ -113,6 +113,30 @@ gint g_param_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value2);
|
||||
|
||||
|
||||
/* --- convenience functions --- */
|
||||
typedef struct _GParamSpecTypeInfo GParamSpecTypeInfo;
|
||||
struct _GParamSpecTypeInfo
|
||||
{
|
||||
/* type system portion */
|
||||
guint16 instance_size; /* obligatory */
|
||||
guint16 n_preallocs; /* optional */
|
||||
void (*instance_init) (GParamSpec *pspec); /* optional */
|
||||
|
||||
/* class portion */
|
||||
GType value_type; /* obligatory */
|
||||
void (*finalize) (GParamSpec *pspec); /* optional */
|
||||
void (*value_set_default) (GParamSpec *pspec, /* recommended */
|
||||
GValue *value);
|
||||
gboolean (*value_validate) (GParamSpec *pspec, /* optional */
|
||||
GValue *value);
|
||||
gint (*values_cmp) (GParamSpec *pspec, /* recommended */
|
||||
const GValue *value1,
|
||||
const GValue *value2);
|
||||
};
|
||||
GType g_param_type_register_static (const gchar *name,
|
||||
const GParamSpecTypeInfo *pspec_info);
|
||||
|
||||
|
||||
/* --- private --- */
|
||||
gpointer g_param_spec_internal (GType param_type,
|
||||
const gchar *name,
|
||||
@@ -134,44 +158,18 @@ GParamSpec* g_param_spec_hash_table_lookup (GHashTable *hash_table,
|
||||
|
||||
/* contracts:
|
||||
*
|
||||
* +++ OUTDATED +++
|
||||
*
|
||||
* class functions may not evaluate param->pspec directly,
|
||||
* instead, pspec will be passed as argument if required.
|
||||
*
|
||||
* void param_init (GParam *param, GParamSpec *pspec):
|
||||
* initialize param's value to default if pspec is given,
|
||||
* and to zero-equivalent (a value that doesn't need to be
|
||||
* free()ed later on) otherwise.
|
||||
*
|
||||
* void param_free_value (GParam *param):
|
||||
* free param's value if required, zero-reinitialization
|
||||
* of the value is not required. (this class function
|
||||
* may be NULL for param types that don't need to free
|
||||
* values, such as ints or floats).
|
||||
*
|
||||
* gboolean param_validate (GParam *param, GParamSpec *pspec):
|
||||
* modify param's value in the least destructive way, so
|
||||
* gboolean value_validate (GParamSpec *pspec,
|
||||
* GValue *value):
|
||||
* modify value contents in the least destructive way, so
|
||||
* that it complies with pspec's requirements (i.e.
|
||||
* according to minimum/maximum ranges etc...). return
|
||||
* whether modification was necessary.
|
||||
*
|
||||
* gint param_values_cmp (GParam *param1, GParam *param2, GParamSpec*):
|
||||
* return param1 - param2, i.e. <0 if param1 < param2,
|
||||
* >0 if param1 > param2, and 0 if they are equal
|
||||
* (passing pspec is optional, but recommended)
|
||||
*
|
||||
* void param_copy_value (GParam *param_src, GParam *param_dest):
|
||||
* copy value from param_src to param_dest, param_dest is
|
||||
* already free()d and zero-initialized, so its value can
|
||||
* simply be overwritten. (may be NULL for memcpy)
|
||||
*
|
||||
* gchar* param_collect_value ():
|
||||
* class function may be NULL.
|
||||
*
|
||||
* gchar* param_lcopy_value ():
|
||||
* class function may be NULL.
|
||||
*
|
||||
* gint values_cmp (GParamSpec *pspec,
|
||||
* const GValue *value1,
|
||||
* const GValue *value2):
|
||||
* return value1 - value2, i.e. <0 if value1 < value2,
|
||||
* >0 if value1 > value2, and 0 otherwise (they are equal)
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "gvaluecollector.h"
|
||||
#include <string.h>
|
||||
#include "config.h" /* for SIZEOF_LONG */
|
||||
#include "../config.h" /* for SIZEOF_LONG */
|
||||
|
||||
#define G_FLOAT_EPSILON (1e-30)
|
||||
#define G_DOUBLE_EPSILON (1e-90)
|
||||
@@ -710,272 +710,229 @@ value_exch_double_float (GValue *value1,
|
||||
|
||||
|
||||
/* --- type initialization --- */
|
||||
typedef struct {
|
||||
GType value_type;
|
||||
void (*finalize) (GParamSpec *pspec);
|
||||
void (*value_set_default) (GParamSpec *pspec,
|
||||
GValue *value);
|
||||
gboolean (*value_validate) (GParamSpec *pspec,
|
||||
GValue *value);
|
||||
gint (*values_cmp) (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2);
|
||||
} ParamSpecClassInfo;
|
||||
|
||||
static void
|
||||
param_spec_class_init (gpointer g_class,
|
||||
gpointer class_data)
|
||||
{
|
||||
GParamSpecClass *class = g_class;
|
||||
ParamSpecClassInfo *info = class_data;
|
||||
|
||||
g_assert (info->value_type && !G_TYPE_IS_PARAM (info->value_type));
|
||||
|
||||
class->value_type = info->value_type;
|
||||
if (info->finalize)
|
||||
class->finalize = info->finalize;
|
||||
if (info->value_set_default)
|
||||
class->value_set_default = info->value_set_default;
|
||||
if (info->value_validate)
|
||||
class->value_validate = info->value_validate;
|
||||
if (info->values_cmp)
|
||||
class->values_cmp = info->values_cmp;
|
||||
}
|
||||
|
||||
void
|
||||
g_param_spec_types_init (void) /* sync with gtype.c */
|
||||
{
|
||||
GTypeInfo info = {
|
||||
sizeof (GParamSpecClass), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_destroy */
|
||||
param_spec_class_init, /* class_init */
|
||||
NULL, /* class_destroy */
|
||||
NULL, /* class_data */
|
||||
0, /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
};
|
||||
GType type;
|
||||
|
||||
/* G_TYPE_PARAM_CHAR
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecChar), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_char_init, /* instance_init */
|
||||
G_TYPE_CHAR, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_char_set_default, /* value_set_default */
|
||||
param_char_validate, /* value_validate */
|
||||
param_int_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecChar);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_char_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamChar", &info);
|
||||
type = g_param_type_register_static ("GParamChar", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_CHAR);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_UCHAR
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecUChar), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_uchar_init, /* instance_init */
|
||||
G_TYPE_UCHAR, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_uchar_set_default, /* value_set_default */
|
||||
param_uchar_validate, /* value_validate */
|
||||
param_uint_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecUChar);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_uchar_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamUChar", &info);
|
||||
type = g_param_type_register_static ("GParamUChar", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_UCHAR);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_BOOLEAN
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
G_TYPE_BOOLEAN, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_boolean_set_default, /* value_set_default */
|
||||
param_boolean_validate, /* value_validate */
|
||||
param_int_values_cmp, /* values_cmp */
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecBoolean), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
NULL, /* instance_init */
|
||||
G_TYPE_BOOLEAN, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_boolean_set_default, /* value_set_default */
|
||||
param_boolean_validate, /* value_validate */
|
||||
param_int_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecBoolean);
|
||||
info.instance_init = (GInstanceInitFunc) NULL;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamBoolean", &info);
|
||||
type = g_param_type_register_static ("GParamBoolean", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_BOOLEAN);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_INT
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecInt), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_int_init, /* instance_init */
|
||||
G_TYPE_INT, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_int_set_default, /* value_set_default */
|
||||
param_int_validate, /* value_validate */
|
||||
param_int_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecInt);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_int_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamInt", &info);
|
||||
type = g_param_type_register_static ("GParamInt", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_INT);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_UINT
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecUInt), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_uint_init, /* instance_init */
|
||||
G_TYPE_UINT, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_uint_set_default, /* value_set_default */
|
||||
param_uint_validate, /* value_validate */
|
||||
param_uint_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecUInt);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_uint_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamUInt", &info);
|
||||
type = g_param_type_register_static ("GParamUInt", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_UINT);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_LONG
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecLong), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_long_init, /* instance_init */
|
||||
G_TYPE_LONG, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_long_set_default, /* value_set_default */
|
||||
param_long_validate, /* value_validate */
|
||||
param_long_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecLong);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_long_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamLong", &info);
|
||||
type = g_param_type_register_static ("GParamLong", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_LONG);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_ULONG
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecULong), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_ulong_init, /* instance_init */
|
||||
G_TYPE_ULONG, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_ulong_set_default, /* value_set_default */
|
||||
param_ulong_validate, /* value_validate */
|
||||
param_ulong_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecULong);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_ulong_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamULong", &info);
|
||||
type = g_param_type_register_static ("GParamULong", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_ULONG);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_ENUM
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecEnum), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_enum_init, /* instance_init */
|
||||
G_TYPE_ENUM, /* value_type */
|
||||
param_spec_enum_finalize, /* finalize */
|
||||
param_enum_set_default, /* value_set_default */
|
||||
param_enum_validate, /* value_validate */
|
||||
param_long_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecEnum);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_enum_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamEnum", &info);
|
||||
type = g_param_type_register_static ("GParamEnum", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_ENUM);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_FLAGS
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecFlags), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_flags_init, /* instance_init */
|
||||
G_TYPE_FLAGS, /* value_type */
|
||||
param_spec_flags_finalize,/* finalize */
|
||||
param_flags_set_default, /* value_set_default */
|
||||
param_flags_validate, /* value_validate */
|
||||
param_ulong_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecFlags);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_flags_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamFlags", &info);
|
||||
type = g_param_type_register_static ("GParamFlags", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_FLAGS);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_FLOAT
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecFloat), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_float_init, /* instance_init */
|
||||
G_TYPE_FLOAT, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_float_set_default, /* value_set_default */
|
||||
param_float_validate, /* value_validate */
|
||||
param_float_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecFloat);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_float_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamFloat", &info);
|
||||
type = g_param_type_register_static ("GParamFloat", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_FLOAT);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_DOUBLE
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
G_TYPE_DOUBLE, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_double_set_default, /* value_set_default */
|
||||
param_double_validate, /* value_validate */
|
||||
param_double_values_cmp, /* values_cmp */
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecDouble), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_double_init, /* instance_init */
|
||||
G_TYPE_DOUBLE, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_double_set_default, /* value_set_default */
|
||||
param_double_validate, /* value_validate */
|
||||
param_double_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecDouble);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_double_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamDouble", &info);
|
||||
type = g_param_type_register_static ("GParamDouble", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_DOUBLE);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_STRING
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecString), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_string_init, /* instance_init */
|
||||
G_TYPE_STRING, /* value_type */
|
||||
param_spec_string_finalize, /* finalize */
|
||||
param_string_set_default, /* value_set_default */
|
||||
param_string_validate, /* value_validate */
|
||||
param_string_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecString);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_string_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamString", &info);
|
||||
type = g_param_type_register_static ("GParamString", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_STRING);
|
||||
}
|
||||
|
||||
/* G_TYPE_PARAM_OBJECT
|
||||
*/
|
||||
{
|
||||
static const ParamSpecClassInfo class_info = {
|
||||
G_TYPE_OBJECT, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_object_set_default, /* value_set_default */
|
||||
param_object_validate, /* value_validate */
|
||||
param_object_values_cmp, /* values_cmp */
|
||||
static const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (GParamSpecObject), /* instance_size */
|
||||
16, /* n_preallocs */
|
||||
param_spec_object_init, /* instance_init */
|
||||
G_TYPE_OBJECT, /* value_type */
|
||||
NULL, /* finalize */
|
||||
param_object_set_default, /* value_set_default */
|
||||
param_object_validate, /* value_validate */
|
||||
param_object_values_cmp, /* values_cmp */
|
||||
};
|
||||
info.class_data = &class_info;
|
||||
info.instance_size = sizeof (GParamSpecObject);
|
||||
info.instance_init = (GInstanceInitFunc) param_spec_object_init;
|
||||
type = g_type_register_static (G_TYPE_PARAM, "GParamObject", &info);
|
||||
type = g_param_type_register_static ("GParamObject", &pspec_info);
|
||||
g_assert (type == G_TYPE_PARAM_OBJECT);
|
||||
}
|
||||
|
||||
|
1335
gobject/gsignal.c
Normal file
1335
gobject/gsignal.c
Normal file
File diff suppressed because it is too large
Load Diff
142
gobject/gsignal.h
Normal file
142
gobject/gsignal.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* GObject - GLib Type, Object, Parameter and Signal Library
|
||||
* Copyright (C) 2000 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __G_SIGNAL_H__
|
||||
#define __G_SIGNAL_H__
|
||||
|
||||
|
||||
#include <gobject/gclosure.h>
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gparam.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* --- macros --- */
|
||||
#define G_SIGNAL_HINT_ID(hint) ((hint) >> 8)
|
||||
#define G_SIGNAL_HINT_RUN_TYPE(hint) ((hint) & 0xff)
|
||||
|
||||
|
||||
/* --- run & match types --- */
|
||||
typedef enum
|
||||
{
|
||||
G_SIGNAL_RUN_FIRST = 1 << 0,
|
||||
G_SIGNAL_RUN_LAST = 1 << 1,
|
||||
G_SIGNAL_RUN_CLEANUP = 1 << 2,
|
||||
G_SIGNAL_NO_RECURSE = 1 << 3,
|
||||
G_SIGNAL_ACTION = 1 << 4,
|
||||
G_SIGNAL_NO_HOOKS = 1 << 5
|
||||
} GSignalType;
|
||||
typedef enum
|
||||
{
|
||||
G_SIGNAL_MATCH_ID = 1 << 0,
|
||||
G_SIGNAL_MATCH_CLOSURE = 1 << 1,
|
||||
G_SIGNAL_MATCH_FUNC = 1 << 2,
|
||||
G_SIGNAL_MATCH_DATA = 1 << 3,
|
||||
G_SIGNAL_MATCH_UNBLOCKED = 1 << 4,
|
||||
G_SIGNAL_MATCH_MASK = 0x1f
|
||||
} GSignalMatchType;
|
||||
|
||||
|
||||
/* --- signal queries --- */
|
||||
typedef struct _GSignalQuery GSignalQuery;
|
||||
struct _GSignalQuery
|
||||
{
|
||||
guint signal_id;
|
||||
const gchar *signal_name;
|
||||
GType itype;
|
||||
GSignalType signal_flags;
|
||||
GType return_type;
|
||||
guint n_params;
|
||||
const GType *param_types;
|
||||
};
|
||||
|
||||
|
||||
/* --- function types --- */
|
||||
typedef gboolean (*GSignalEmissionHook) (guint signal_id,
|
||||
guint n_values,
|
||||
const GValue *values);
|
||||
typedef gboolean (*GSignalAccumulator) (guint signal_id,
|
||||
GValue *return_accu,
|
||||
const GValue *return_value);
|
||||
typedef GClosureMarshal GSignalCMarshaller;
|
||||
|
||||
|
||||
/* --- signals --- */
|
||||
guint g_signal_newv (const gchar *signal_name,
|
||||
GType itype,
|
||||
GSignalType signal_flags,
|
||||
GClosure *class_closure,
|
||||
GSignalAccumulator accumulator,
|
||||
GSignalCMarshaller c_marshaller,
|
||||
GType return_type,
|
||||
guint n_params,
|
||||
GType *param_types);
|
||||
void g_signal_emitv (const GValue *instance_and_params,
|
||||
guint signal_id,
|
||||
GValue *return_value);
|
||||
guint g_signal_lookup (const gchar *name,
|
||||
GType itype);
|
||||
gchar* g_signal_name (guint signal_id);
|
||||
void g_signal_query (guint signal_id,
|
||||
GSignalQuery *query);
|
||||
|
||||
|
||||
/* --- signal handlers --- */
|
||||
guint g_signal_connect_closure (gpointer instance,
|
||||
guint signal_id,
|
||||
GClosure *closure,
|
||||
gboolean after);
|
||||
void g_signal_handler_disconnect (gpointer instance,
|
||||
guint handler_id);
|
||||
void g_signal_handler_block (gpointer instance,
|
||||
guint handler_id);
|
||||
void g_signal_handler_unblock (gpointer instance,
|
||||
guint handler_id);
|
||||
guint g_signal_handler_find (gpointer instance,
|
||||
GSignalMatchType mask,
|
||||
guint signal_id,
|
||||
GClosure *closure,
|
||||
gpointer func,
|
||||
gpointer data);
|
||||
gboolean g_signal_has_handler_pending (gpointer instance,
|
||||
guint signal_id,
|
||||
gboolean may_be_blocked);
|
||||
|
||||
|
||||
/* --- signal emissions --- */
|
||||
void g_signal_stop_emission (gpointer instance,
|
||||
guint signal_id);
|
||||
guint g_signal_add_emission_hook_full (guint signal_id,
|
||||
GClosure *closure);
|
||||
void g_signal_remove_emission_hook (guint signal_id,
|
||||
guint hook_id);
|
||||
|
||||
/*< private >*/
|
||||
void g_signal_handlers_destroy (gpointer instance);
|
||||
void g_signals_destroy (GType itype);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __G_SIGNAL_H__ */
|
221
gobject/gtype.c
221
gobject/gtype.c
@@ -32,20 +32,26 @@
|
||||
* TODO:
|
||||
* - g_type_from_name() should do an ordered array lookup after fetching the
|
||||
* the quark, instead of a second hashtable lookup.
|
||||
* - speedup checks for virtual types, steal a bit somewhere
|
||||
*
|
||||
* FIXME:
|
||||
* - force interface initialization for already existing classes
|
||||
* - make things threadsafe
|
||||
*/
|
||||
|
||||
#define G_TYPE_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
|
||||
G_TYPE_FLAG_INSTANTIATABLE | \
|
||||
G_TYPE_FLAG_DERIVABLE | \
|
||||
G_TYPE_FLAG_DEEP_DERIVABLE)
|
||||
#define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
|
||||
G_TYPE_FLAG_INSTANTIATABLE | \
|
||||
G_TYPE_FLAG_DERIVABLE | \
|
||||
G_TYPE_FLAG_DEEP_DERIVABLE)
|
||||
#define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT)
|
||||
|
||||
#define g_type_plugin_ref(p) ((p)->vtable->plugin_ref (p))
|
||||
#define g_type_plugin_unref(p) ((p)->vtable->plugin_unref (p))
|
||||
#define g_type_plugin_complete_type_info(p,t,i,v) ((p)->vtable->complete_type_info ((p), (t), (i), (v)))
|
||||
#define g_type_plugin_complete_interface_info(p,f,t,i) ((p)->vtable->complete_interface_info ((p), (f), (t), (i)))
|
||||
|
||||
|
||||
/* --- typedefs --- */
|
||||
typedef struct _TypeNode TypeNode;
|
||||
typedef struct _CommonData CommonData;
|
||||
typedef struct _IFaceData IFaceData;
|
||||
@@ -58,6 +64,8 @@ typedef struct _IFaceHolder IFaceHolder;
|
||||
|
||||
/* --- prototypes --- */
|
||||
static inline GTypeFundamentalInfo* type_node_fundamental_info (TypeNode *node);
|
||||
static void type_add_flags (TypeNode *node,
|
||||
GTypeFlags flags);
|
||||
static void type_data_make (TypeNode *node,
|
||||
const GTypeInfo *info,
|
||||
const GTypeValueTable *value_table);
|
||||
@@ -69,6 +77,10 @@ static void type_data_last_unref (GType type,
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
struct _GValue /* kludge, keep in sync with gvalue.h */
|
||||
{
|
||||
GType g_type;
|
||||
};
|
||||
struct _TypeNode
|
||||
{
|
||||
GTypePlugin *plugin;
|
||||
@@ -159,11 +171,12 @@ typedef struct {
|
||||
/* --- variables --- */
|
||||
static guint n_class_cache_funcs = 0;
|
||||
static ClassCacheFunc *class_cache_funcs = NULL;
|
||||
static GType last_fundamental_id = 0;
|
||||
static GQuark quark_type_flags = 0;
|
||||
|
||||
|
||||
/* --- externs --- */
|
||||
const char *g_log_domain_gobject = "GLib-Object";
|
||||
static GType last_fundamental_id = 0;
|
||||
|
||||
|
||||
/* --- type nodes --- */
|
||||
@@ -187,11 +200,11 @@ LOOKUP_TYPE_NODE (register GType utype)
|
||||
#define NODE_NAME(node) (g_quark_to_string (node->qname))
|
||||
|
||||
static TypeNode*
|
||||
type_node_any_new (TypeNode *pnode,
|
||||
GType ftype,
|
||||
const gchar *name,
|
||||
GTypePlugin *plugin,
|
||||
GTypeFlags type_flags)
|
||||
type_node_any_new (TypeNode *pnode,
|
||||
GType ftype,
|
||||
const gchar *name,
|
||||
GTypePlugin *plugin,
|
||||
GTypeFundamentalFlags type_flags)
|
||||
{
|
||||
guint branch_last, n_supers = pnode ? pnode->n_supers + 1 : 0;
|
||||
GType type;
|
||||
@@ -204,11 +217,11 @@ type_node_any_new (TypeNode *pnode,
|
||||
g_type_nodes[ftype] = g_renew (TypeNode*, g_type_nodes[ftype], 1 << g_bit_storage (g_branch_seqnos[ftype] - 1));
|
||||
|
||||
if (!pnode)
|
||||
node_size += sizeof (GTypeFundamentalInfo); /* fundamental type info */
|
||||
node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
|
||||
node_size += sizeof (GTypeFundamentalInfo); /* fundamental type info */
|
||||
node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
|
||||
node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + 0 for ->supers[] */
|
||||
node = g_malloc0 (node_size);
|
||||
if (!pnode) /* fundamental type */
|
||||
if (!pnode) /* offset fundamental types */
|
||||
node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
|
||||
g_type_nodes[ftype][branch_last] = node;
|
||||
|
||||
@@ -280,9 +293,9 @@ type_node_fundamental_info (TypeNode *node)
|
||||
}
|
||||
|
||||
static TypeNode*
|
||||
type_node_fundamental_new (GType ftype,
|
||||
const gchar *name,
|
||||
GTypeFlags type_flags)
|
||||
type_node_fundamental_new (GType ftype,
|
||||
const gchar *name,
|
||||
GTypeFundamentalFlags type_flags)
|
||||
{
|
||||
GTypeFundamentalInfo *finfo;
|
||||
TypeNode *node;
|
||||
@@ -290,7 +303,7 @@ type_node_fundamental_new (GType ftype,
|
||||
|
||||
g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
|
||||
|
||||
type_flags &= G_TYPE_FLAG_MASK;
|
||||
type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
|
||||
|
||||
last_fundamental_id = MAX (last_fundamental_id, ftype + 1);
|
||||
if (last_fundamental_id > flast)
|
||||
@@ -495,6 +508,7 @@ check_value_table (const gchar *type_name,
|
||||
else if (value_table->value_init == NULL)
|
||||
{
|
||||
if (value_table->value_free || value_table->value_copy ||
|
||||
value_table->value_peek_pointer ||
|
||||
value_table->collect_type || value_table->collect_value ||
|
||||
value_table->lcopy_type || value_table->lcopy_value)
|
||||
g_warning ("cannot handle uninitializable values of type `%s'",
|
||||
@@ -695,6 +709,25 @@ check_interface_info (TypeNode *iface,
|
||||
|
||||
|
||||
/* --- type info (type node data) --- */
|
||||
static void
|
||||
type_add_flags (TypeNode *node,
|
||||
GTypeFlags flags)
|
||||
{
|
||||
guint dflags;
|
||||
|
||||
g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
|
||||
g_return_if_fail (node != NULL);
|
||||
|
||||
if (!quark_type_flags)
|
||||
quark_type_flags = g_quark_from_static_string ("GTypeFlags");
|
||||
if ((flags & G_TYPE_FLAG_ABSTRACT) && node->is_classed &&
|
||||
node->data && node->data->class.class)
|
||||
g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
|
||||
dflags = GPOINTER_TO_UINT (g_type_get_qdata (NODE_TYPE (node), quark_type_flags));
|
||||
dflags |= flags;
|
||||
g_type_set_qdata (NODE_TYPE (node), quark_type_flags, GUINT_TO_POINTER (dflags));
|
||||
}
|
||||
|
||||
static void
|
||||
type_data_make (TypeNode *node,
|
||||
const GTypeInfo *info,
|
||||
@@ -856,10 +889,10 @@ type_node_add_iface_entry (TypeNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
type_add_interface (TypeNode *node,
|
||||
TypeNode *iface,
|
||||
GInterfaceInfo *info,
|
||||
GTypePlugin *plugin)
|
||||
type_add_interface (TypeNode *node,
|
||||
TypeNode *iface,
|
||||
const GInterfaceInfo *info,
|
||||
GTypePlugin *plugin)
|
||||
{
|
||||
IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
|
||||
|
||||
@@ -943,6 +976,12 @@ g_type_create_instance (GType type)
|
||||
type_descriptive_name (type));
|
||||
return NULL;
|
||||
}
|
||||
if (G_TYPE_IS_ABSTRACT (type))
|
||||
{
|
||||
g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
|
||||
type_descriptive_name (type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class = g_type_class_ref (type);
|
||||
|
||||
@@ -992,8 +1031,15 @@ g_type_free_instance (GTypeInstance *instance)
|
||||
type_descriptive_name (class->g_type));
|
||||
return;
|
||||
}
|
||||
if (G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
|
||||
{
|
||||
g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
|
||||
NODE_NAME (node));
|
||||
return;
|
||||
}
|
||||
|
||||
instance->g_class = NULL;
|
||||
memset (instance, 0xaa, node->data->instance.instance_size); // FIXME
|
||||
if (node->data->instance.n_preallocs)
|
||||
g_chunk_free (instance, node->data->instance.mem_chunk);
|
||||
else
|
||||
@@ -1282,7 +1328,8 @@ GType
|
||||
g_type_register_fundamental (GType type_id,
|
||||
const gchar *type_name,
|
||||
const GTypeInfo *info,
|
||||
const GTypeFundamentalInfo *finfo)
|
||||
const GTypeFundamentalInfo *finfo,
|
||||
GTypeFlags flags)
|
||||
{
|
||||
GTypeFundamentalInfo *node_finfo;
|
||||
TypeNode *node;
|
||||
@@ -1318,6 +1365,7 @@ g_type_register_fundamental (GType type_id,
|
||||
|
||||
node = type_node_fundamental_new (type_id, type_name, finfo->type_flags);
|
||||
node_finfo = type_node_fundamental_info (node);
|
||||
type_add_flags (node, flags);
|
||||
|
||||
if (!check_type_info (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
|
||||
return NODE_TYPE (node);
|
||||
@@ -1330,7 +1378,8 @@ g_type_register_fundamental (GType type_id,
|
||||
GType
|
||||
g_type_register_static (GType parent_type,
|
||||
const gchar *type_name,
|
||||
const GTypeInfo *info)
|
||||
const GTypeInfo *info,
|
||||
GTypeFlags flags)
|
||||
{
|
||||
TypeNode *pnode, *node;
|
||||
GType type;
|
||||
@@ -1351,12 +1400,13 @@ g_type_register_static (GType parent_type,
|
||||
return 0;
|
||||
if (info->class_finalize)
|
||||
{
|
||||
g_warning ("class destructor specified for static type `%s'",
|
||||
g_warning ("class finalizer specified for static type `%s'",
|
||||
type_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = type_node_new (pnode, type_name, NULL);
|
||||
type_add_flags (node, flags);
|
||||
type = NODE_TYPE (node);
|
||||
type_data_make (node, info,
|
||||
check_value_table (type_name, info->value_table) ? info->value_table : NULL);
|
||||
@@ -1367,7 +1417,8 @@ g_type_register_static (GType parent_type,
|
||||
GType
|
||||
g_type_register_dynamic (GType parent_type,
|
||||
const gchar *type_name,
|
||||
GTypePlugin *plugin)
|
||||
GTypePlugin *plugin,
|
||||
GTypeFlags flags)
|
||||
{
|
||||
TypeNode *pnode, *node;
|
||||
GType type;
|
||||
@@ -1385,15 +1436,16 @@ g_type_register_dynamic (GType parent_type,
|
||||
pnode = LOOKUP_TYPE_NODE (parent_type);
|
||||
|
||||
node = type_node_new (pnode, type_name, plugin);
|
||||
type_add_flags (node, flags);
|
||||
type = NODE_TYPE (node);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
g_type_add_interface_static (GType instance_type,
|
||||
GType interface_type,
|
||||
GInterfaceInfo *info)
|
||||
g_type_add_interface_static (GType instance_type,
|
||||
GType interface_type,
|
||||
const GInterfaceInfo *info)
|
||||
{
|
||||
TypeNode *node;
|
||||
TypeNode *iface;
|
||||
@@ -1674,11 +1726,7 @@ g_type_conforms_to (GType type,
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeNode *node = LOOKUP_TYPE_NODE (type);
|
||||
|
||||
return node && (node->is_iface || node->is_instantiatable);
|
||||
}
|
||||
return LOOKUP_TYPE_NODE (type) != NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1839,20 +1887,34 @@ g_type_set_qdata (GType type,
|
||||
|
||||
/* --- implementation details --- */
|
||||
gboolean
|
||||
g_type_check_flags (GType type,
|
||||
GTypeFlags flags)
|
||||
g_type_check_flags (GType type,
|
||||
guint flags)
|
||||
{
|
||||
TypeNode *node = LOOKUP_TYPE_NODE (type);
|
||||
|
||||
flags &= G_TYPE_FLAG_MASK;
|
||||
gboolean result = FALSE;
|
||||
|
||||
if (node)
|
||||
{
|
||||
GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
|
||||
guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
|
||||
guint tflags = flags & TYPE_FLAG_MASK;
|
||||
|
||||
if (fflags)
|
||||
{
|
||||
GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
|
||||
|
||||
fflags = (finfo->type_flags & fflags) == fflags;
|
||||
}
|
||||
else
|
||||
fflags = TRUE;
|
||||
|
||||
return (finfo->type_flags & flags) != 0;
|
||||
if (tflags)
|
||||
tflags = (tflags & GPOINTER_TO_UINT (g_type_get_qdata (type, quark_type_flags))) == tflags;
|
||||
else
|
||||
tflags = TRUE;
|
||||
|
||||
result = tflags && fflags;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
GTypePlugin*
|
||||
@@ -1874,6 +1936,7 @@ g_type_instance_conforms_to (GTypeInstance *type_instance,
|
||||
GType iface_type)
|
||||
{
|
||||
return (type_instance && type_instance->g_class &&
|
||||
G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type) &&
|
||||
g_type_conforms_to (type_instance->g_class->g_type, iface_type));
|
||||
}
|
||||
|
||||
@@ -1881,7 +1944,35 @@ gboolean
|
||||
g_type_class_is_a (GTypeClass *type_class,
|
||||
GType is_a_type)
|
||||
{
|
||||
return (type_class && g_type_is_a (type_class->g_type, is_a_type));
|
||||
return (type_class && G_TYPE_IS_CLASSED (type_class->g_type) &&
|
||||
g_type_is_a (type_class->g_type, is_a_type));
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_type_value_conforms_to (GValue *value,
|
||||
GType type)
|
||||
{
|
||||
TypeNode *node;
|
||||
|
||||
if (!value)
|
||||
return FALSE;
|
||||
node = LOOKUP_TYPE_NODE (value->g_type);
|
||||
#if 0
|
||||
if (!G_TYPE_IS_FUNDAMENTAL (value->g_type) && !node || !node->data)
|
||||
node = LOOKUP_TYPE_NODE (G_TYPE_FUNDAMENTAL (value->g_type));
|
||||
#endif
|
||||
if (!node || !node->data || node->data->common.ref_count < 1 ||
|
||||
!node->data->common.value_table->value_init ||
|
||||
!g_type_conforms_to (value->g_type, type))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_type_check_value (GValue *value)
|
||||
{
|
||||
return value && g_type_value_conforms_to (value, value->g_type);
|
||||
}
|
||||
|
||||
GTypeInstance*
|
||||
@@ -1900,9 +1991,9 @@ g_type_check_instance_cast (GTypeInstance *type_instance,
|
||||
type_descriptive_name (iface_type));
|
||||
return type_instance;
|
||||
}
|
||||
if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
|
||||
if (!G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type))
|
||||
{
|
||||
g_warning ("invalid unclassed type `%s' in cast to `%s'",
|
||||
g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
|
||||
type_descriptive_name (type_instance->g_class->g_type),
|
||||
type_descriptive_name (iface_type));
|
||||
return type_instance;
|
||||
@@ -1946,13 +2037,47 @@ g_type_check_class_cast (GTypeClass *type_class,
|
||||
return type_class;
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_type_check_instance (GTypeInstance *type_instance)
|
||||
{
|
||||
/* this function is just here to make the signal system
|
||||
* conveniently elaborated on instance checks
|
||||
*/
|
||||
if (!type_instance)
|
||||
{
|
||||
g_warning ("instance is invalid (NULL) pointer");
|
||||
return FALSE;
|
||||
}
|
||||
if (!type_instance->g_class)
|
||||
{
|
||||
g_warning ("instance with invalid (NULL) class pointer");
|
||||
return FALSE;
|
||||
}
|
||||
if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
|
||||
{
|
||||
g_warning ("instance of invalid unclassed type `%s'",
|
||||
type_descriptive_name (type_instance->g_class->g_type));
|
||||
return FALSE;
|
||||
}
|
||||
if (!G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type))
|
||||
{
|
||||
g_warning ("instance of invalid non-instantiatable type `%s'",
|
||||
type_descriptive_name (type_instance->g_class->g_type));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* --- foreign prototypes --- */
|
||||
extern void g_value_types_init (void); /* sync with gvaluetypes.c */
|
||||
extern void g_enum_types_init (void); /* sync with genums.c */
|
||||
extern void g_param_type_init (void); /* sync with gparam.c */
|
||||
extern void g_boxed_type_init (void); /* sync with gboxed.c */
|
||||
extern void g_object_type_init (void); /* sync with gobject.c */
|
||||
extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
|
||||
extern void g_signal_init (void); /* sync with gsignal.c */
|
||||
|
||||
|
||||
/* --- initialization --- */
|
||||
@@ -2004,6 +2129,10 @@ g_type_init (void)
|
||||
*/
|
||||
g_param_type_init ();
|
||||
|
||||
/* G_TYPE_PARAM
|
||||
*/
|
||||
g_boxed_type_init ();
|
||||
|
||||
/* G_TYPE_OBJECT
|
||||
*/
|
||||
g_object_type_init ();
|
||||
@@ -2011,4 +2140,8 @@ g_type_init (void)
|
||||
/* G_TYPE_PARAM_* pspec types
|
||||
*/
|
||||
g_param_spec_types_init ();
|
||||
|
||||
/* Signal system
|
||||
*/
|
||||
g_signal_init ();
|
||||
}
|
||||
|
106
gobject/gtype.h
106
gobject/gtype.h
@@ -60,11 +60,11 @@ typedef enum /*< skip >*/
|
||||
G_TYPE_DOUBLE,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_PARAM,
|
||||
G_TYPE_BOXED,
|
||||
G_TYPE_POINTER,
|
||||
G_TYPE_OBJECT,
|
||||
|
||||
/* the following reserved ids should vanish soon */
|
||||
G_TYPE_GTK_BOXED,
|
||||
G_TYPE_GTK_POINTER,
|
||||
G_TYPE_GTK_SIGNAL,
|
||||
|
||||
/* reserved fundamental type ids,
|
||||
@@ -99,12 +99,15 @@ typedef enum /*< skip >*/
|
||||
|
||||
/* Type Checking Macros
|
||||
*/
|
||||
#define G_TYPE_IS_FUNDAMENTAL(type) (G_TYPE_BRANCH_SEQNO (type) == 0)
|
||||
#define G_TYPE_IS_INTERFACE(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_INTERFACE)
|
||||
#define G_TYPE_IS_CLASSED(type) (g_type_check_flags ((type), G_TYPE_FLAG_CLASSED))
|
||||
#define G_TYPE_IS_INSTANTIATABLE(type) (g_type_check_flags ((type), G_TYPE_FLAG_INSTANTIATABLE))
|
||||
#define G_TYPE_IS_DERIVABLE(type) (g_type_check_flags ((type), G_TYPE_FLAG_DERIVABLE))
|
||||
#define G_TYPE_IS_DEEP_DERIVABLE(type) (g_type_check_flags ((type), G_TYPE_FLAG_DEEP_DERIVABLE))
|
||||
#define G_TYPE_IS_ABSTRACT(type) (g_type_check_flags ((type), G_TYPE_FLAG_ABSTRACT))
|
||||
#define G_TYPE_IS_PARAM(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_PARAM)
|
||||
#define G_TYPE_IS_VALUE_TYPE(type) (g_type_value_table_peek (type) != NULL)
|
||||
|
||||
|
||||
/* Typedefs
|
||||
@@ -143,13 +146,20 @@ struct _GTypeInterface
|
||||
};
|
||||
|
||||
|
||||
/* Casts, Checks And Convenience Macros For Structured Types
|
||||
/* Casts, checks and accessors for structured types
|
||||
* usage of these macros is reserved to type implementations only
|
||||
*
|
||||
*/
|
||||
/*< protected >*/
|
||||
#define G_TYPE_CHECK_INSTANCE(instance) (_G_TYPE_CHI ((GTypeInstance*) (instance)))
|
||||
#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type))
|
||||
#define G_TYPE_CHECK_CLASS_CAST(g_class, g_type, c_type) (_G_TYPE_CCC ((g_class), (g_type), c_type))
|
||||
#define G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type) (_G_TYPE_CIT ((instance), (g_type)))
|
||||
#define G_TYPE_CHECK_CLASS_TYPE(g_class, g_type) (_G_TYPE_CCT ((g_class), (g_type)))
|
||||
#define G_TYPE_INSTANCE_GET_CLASS(instance, g_type, c_type) (_G_TYPE_IGC ((instance), c_type))
|
||||
#define G_TYPE_INSTANCE_GET_INTERFACE(instance, g_type, c_type) (_G_TYPE_IGI ((instance), (g_type), c_type))
|
||||
#define G_TYPE_CHECK_CLASS_CAST(g_class, g_type, c_type) (_G_TYPE_CCC ((g_class), (g_type), c_type))
|
||||
#define G_TYPE_CHECK_CLASS_TYPE(g_class, g_type) (_G_TYPE_CCT ((g_class), (g_type)))
|
||||
#define G_TYPE_CHECK_VALUE(value) (_G_TYPE_CHV ((value)))
|
||||
#define G_TYPE_CHECK_VALUE_TYPE(value, g_type) (_G_TYPE_CVT ((value), (g_type)))
|
||||
#define G_TYPE_FROM_INSTANCE(instance) (G_TYPE_FROM_CLASS (((GTypeInstance*) (instance))->g_class))
|
||||
#define G_TYPE_FROM_CLASS(g_class) (((GTypeClass*) (g_class))->g_type)
|
||||
#define G_TYPE_FROM_INTERFACE(g_iface) (((GTypeInterface*) (g_iface))->g_type)
|
||||
@@ -229,6 +239,10 @@ typedef enum /*< skip >*/
|
||||
G_TYPE_FLAG_INSTANTIATABLE = (1 << 1),
|
||||
G_TYPE_FLAG_DERIVABLE = (1 << 2),
|
||||
G_TYPE_FLAG_DEEP_DERIVABLE = (1 << 3)
|
||||
} GTypeFundamentalFlags;
|
||||
typedef enum /*< skip >*/
|
||||
{
|
||||
G_TYPE_FLAG_ABSTRACT = (1 << 4)
|
||||
} GTypeFlags;
|
||||
struct _GTypeInfo
|
||||
{
|
||||
@@ -253,7 +267,7 @@ struct _GTypeInfo
|
||||
};
|
||||
struct _GTypeFundamentalInfo
|
||||
{
|
||||
GTypeFlags type_flags;
|
||||
GTypeFundamentalFlags type_flags;
|
||||
};
|
||||
struct _GInterfaceInfo
|
||||
{
|
||||
@@ -263,61 +277,72 @@ struct _GInterfaceInfo
|
||||
};
|
||||
struct _GTypeValueTable
|
||||
{
|
||||
void (*value_init) (GValue *value);
|
||||
void (*value_free) (GValue *value);
|
||||
void (*value_copy) (const GValue *src_value,
|
||||
GValue *dest_value);
|
||||
void (*value_init) (GValue *value);
|
||||
void (*value_free) (GValue *value);
|
||||
void (*value_copy) (const GValue *src_value,
|
||||
GValue *dest_value);
|
||||
/* varargs functionality (optional) */
|
||||
guint collect_type;
|
||||
gchar* (*collect_value) (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
guint lcopy_type;
|
||||
gchar* (*lcopy_value) (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
gpointer (*value_peek_pointer) (const GValue *value);
|
||||
guint collect_type;
|
||||
gchar* (*collect_value) (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
guint lcopy_type;
|
||||
gchar* (*lcopy_value) (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value);
|
||||
};
|
||||
GType g_type_register_static (GType parent_type,
|
||||
const gchar *type_name,
|
||||
const GTypeInfo *info);
|
||||
const GTypeInfo *info,
|
||||
GTypeFlags flags);
|
||||
GType g_type_register_dynamic (GType parent_type,
|
||||
const gchar *type_name,
|
||||
GTypePlugin *plugin);
|
||||
GTypePlugin *plugin,
|
||||
GTypeFlags flags);
|
||||
GType g_type_register_fundamental (GType type_id,
|
||||
const gchar *type_name,
|
||||
const GTypeInfo *info,
|
||||
const GTypeFundamentalInfo *finfo);
|
||||
const GTypeFundamentalInfo *finfo,
|
||||
GTypeFlags flags);
|
||||
void g_type_add_interface_static (GType instance_type,
|
||||
GType interface_type,
|
||||
GInterfaceInfo *info);
|
||||
const GInterfaceInfo *info);
|
||||
void g_type_add_interface_dynamic (GType instance_type,
|
||||
GType interface_type,
|
||||
GTypePlugin *plugin);
|
||||
|
||||
|
||||
/* --- implementation details --- */
|
||||
gboolean g_type_class_is_a (GTypeClass *g_class,
|
||||
GType is_a_type);
|
||||
GTypeClass* g_type_check_class_cast (GTypeClass *g_class,
|
||||
GType is_a_type);
|
||||
GTypeInstance* g_type_check_instance_cast (GTypeInstance *instance,
|
||||
GType iface_type);
|
||||
gboolean g_type_instance_conforms_to (GTypeInstance *instance,
|
||||
GType iface_type);
|
||||
/* --- protected (for fundamental type implementations) --- */
|
||||
GTypePlugin* g_type_get_plugin (GType type);
|
||||
GType g_type_fundamental_last (void);
|
||||
gboolean g_type_check_flags (GType type,
|
||||
GTypeFlags flags);
|
||||
guint flags);
|
||||
GTypeInstance* g_type_create_instance (GType type);
|
||||
void g_type_free_instance (GTypeInstance *instance);
|
||||
GTypeValueTable* g_type_value_table_peek (GType type);
|
||||
void g_type_add_class_cache_func (gpointer cache_data,
|
||||
GTypeClassCacheFunc cache_func);
|
||||
void g_type_remove_class_cache_func (gpointer cache_data,
|
||||
GTypeClassCacheFunc cache_func);
|
||||
void g_type_class_unref_uncached (gpointer g_class);
|
||||
GTypePlugin* g_type_get_plugin (GType type);
|
||||
GType g_type_fundamental_last (void);
|
||||
|
||||
|
||||
/*< private >*/
|
||||
GTypeClass* g_type_check_class_cast (GTypeClass *g_class,
|
||||
GType is_a_type);
|
||||
gboolean g_type_class_is_a (GTypeClass *g_class,
|
||||
GType is_a_type);
|
||||
GTypeInstance* g_type_check_instance_cast (GTypeInstance *instance,
|
||||
GType iface_type);
|
||||
gboolean g_type_instance_conforms_to (GTypeInstance *instance,
|
||||
GType iface_type);
|
||||
gboolean g_type_check_value (GValue *value);
|
||||
gboolean g_type_value_conforms_to (GValue *value,
|
||||
GType type);
|
||||
gboolean g_type_check_instance (GTypeInstance *instance);
|
||||
GTypeValueTable* g_type_value_table_peek (GType type);
|
||||
|
||||
|
||||
#ifndef G_DISABLE_CAST_CHECKS
|
||||
@@ -329,9 +354,14 @@ GType g_type_fundamental_last (void);
|
||||
# define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
|
||||
# define _G_TYPE_CCC(cp, gt, ct) ((ct*) cp)
|
||||
#endif /* G_DISABLE_CAST_CHECKS */
|
||||
#define _G_TYPE_IGC(ip, ct) ((ct*) (((GTypeInstance*) ip)->g_class))
|
||||
#define _G_TYPE_CHI(ip) (g_type_check_instance ((GTypeInstance*) ip))
|
||||
#define _G_TYPE_CIT(ip, gt) (g_type_instance_conforms_to ((GTypeInstance*) ip, gt))
|
||||
#define _G_TYPE_CCT(cp, gt) (g_type_class_is_a ((GTypeClass*) cp, gt))
|
||||
#define _G_TYPE_CVT(vl, gt) (g_type_value_conforms_to ((GValue*) vl, gt))
|
||||
#define _G_TYPE_CHV(vl) (g_type_check_value ((GValue*) vl))
|
||||
#define _G_TYPE_IGC(ip, ct) ((ct*) (((GTypeInstance*) ip)->g_class))
|
||||
#define _G_TYPE_IGI(ip, gt, ct) ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -61,11 +61,13 @@ void
|
||||
g_value_copy (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
{
|
||||
GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (dest_value));
|
||||
GTypeValueTable *value_table;
|
||||
|
||||
g_return_if_fail (G_IS_VALUE (src_value));
|
||||
g_return_if_fail (G_IS_VALUE (dest_value));
|
||||
g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)));
|
||||
|
||||
value_table = g_type_value_table_peek (G_VALUE_TYPE (dest_value));
|
||||
if (!value_table)
|
||||
g_return_if_fail (g_type_value_table_peek (G_VALUE_TYPE (dest_value)) != NULL);
|
||||
|
||||
@@ -78,6 +80,36 @@ g_value_copy (const GValue *src_value,
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_value_fits_pointer (const GValue *value)
|
||||
{
|
||||
GTypeValueTable *value_table;
|
||||
|
||||
g_return_val_if_fail (G_IS_VALUE (value), FALSE);
|
||||
|
||||
value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
|
||||
if (!value_table)
|
||||
g_return_val_if_fail (g_type_value_table_peek (G_VALUE_TYPE (value)) != NULL, FALSE);
|
||||
|
||||
return value_table->value_peek_pointer != NULL;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_value_get_as_pointer (const GValue *value)
|
||||
{
|
||||
GTypeValueTable *value_table;
|
||||
|
||||
g_return_val_if_fail (G_IS_VALUE (value), NULL);
|
||||
|
||||
value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
|
||||
if (!value_table)
|
||||
g_return_val_if_fail (g_type_value_table_peek (G_VALUE_TYPE (value)) != NULL, NULL);
|
||||
if (!value_table->value_peek_pointer)
|
||||
g_return_val_if_fail (g_value_fits_pointer (value) == TRUE, NULL);
|
||||
|
||||
return value_table->value_peek_pointer (value);
|
||||
}
|
||||
|
||||
void
|
||||
g_value_unset (GValue *value)
|
||||
{
|
||||
@@ -189,8 +221,8 @@ g_value_register_exchange_func (GType value_type1,
|
||||
{
|
||||
ExchangeEntry entry;
|
||||
|
||||
g_return_if_fail (G_TYPE_IS_VALUE (value_type1));
|
||||
g_return_if_fail (G_TYPE_IS_VALUE (value_type2));
|
||||
g_return_if_fail (g_type_name (value_type1) != NULL);
|
||||
g_return_if_fail (g_type_name (value_type2) != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
entry.value_type1 = MIN (value_type1, value_type2);
|
||||
@@ -218,7 +250,7 @@ gboolean
|
||||
g_value_types_exchangable (GType value_type1,
|
||||
GType value_type2)
|
||||
{
|
||||
g_return_val_if_fail (G_TYPE_IS_VALUE (value_type1), FALSE);
|
||||
g_return_val_if_fail (G_TYPE_IS_VALUE (value_type1), FALSE); /* these might bite us, think G_TYPE_ENUM */
|
||||
g_return_val_if_fail (G_TYPE_IS_VALUE (value_type2), FALSE);
|
||||
|
||||
return exchange_func_lookup (value_type1, value_type2, NULL) != NULL;
|
||||
|
@@ -31,8 +31,9 @@ extern "C" {
|
||||
|
||||
/* --- type macros --- */
|
||||
#define G_TYPE_IS_VALUE(type) (g_type_value_table_peek (type) != NULL)
|
||||
#define G_IS_VALUE(value) (G_TYPE_IS_VALUE (G_VALUE_TYPE (value))) /* FIXME */
|
||||
#define G_VALUE_TYPE(value) (G_TYPE_FROM_CLASS (value))
|
||||
#define G_IS_VALUE(value) (G_TYPE_CHECK_VALUE (value))
|
||||
#define G_VALUE_HOLDS(value, g_type) (G_TYPE_CHECK_VALUE_TYPE ((value), (g_type)))
|
||||
#define G_VALUE_TYPE(value) (((GValue*) (value))->g_type)
|
||||
#define G_VALUE_TYPE_NAME(value) (g_type_name (G_VALUE_TYPE (value)))
|
||||
|
||||
|
||||
@@ -66,6 +67,8 @@ gboolean g_value_convert (const GValue *src_value,
|
||||
GValue *dest_value);
|
||||
void g_value_reset (GValue *value);
|
||||
void g_value_unset (GValue *value);
|
||||
gboolean g_value_fits_pointer (const GValue *value);
|
||||
gpointer g_value_get_as_pointer (const GValue *value);
|
||||
|
||||
|
||||
/* --- implementation details --- */
|
||||
|
@@ -260,6 +260,54 @@ value_string_lcopy_value (const GValue *value,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
value_pointer_init (GValue *value)
|
||||
{
|
||||
value->data[0].v_pointer = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
value_pointer_copy (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
{
|
||||
dest_value->data[0].v_pointer = src_value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
value_pointer_peek_pointer (const GValue *value)
|
||||
{
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
value_pointer_collect_value (GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
value->data[0].v_pointer = collect_value->v_pointer;
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
value_pointer_lcopy_value (const GValue *value,
|
||||
guint nth_value,
|
||||
GType *collect_type,
|
||||
GTypeCValue *collect_value)
|
||||
{
|
||||
gpointer *pointer_p = collect_value->v_pointer;
|
||||
|
||||
if (!pointer_p)
|
||||
return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
|
||||
|
||||
*pointer_p = value->data[0].v_pointer;
|
||||
|
||||
*collect_type = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* --- type initialization --- */
|
||||
void
|
||||
@@ -287,15 +335,16 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_long0_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_long0_copy, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_INT, /* collect_type */
|
||||
value_int_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_char_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_CHAR);
|
||||
type = g_type_register_fundamental (G_TYPE_UCHAR, "guchar", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_UCHAR, "guchar", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_UCHAR);
|
||||
}
|
||||
|
||||
@@ -306,13 +355,14 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_long0_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_long0_copy, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_INT, /* collect_type */
|
||||
value_int_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_boolean_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_BOOLEAN, "gboolean", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_BOOLEAN, "gboolean", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_BOOLEAN);
|
||||
}
|
||||
|
||||
@@ -323,15 +373,16 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_long0_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_long0_copy, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_INT, /* collect_type */
|
||||
value_int_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_int_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_INT, "gint", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_INT, "gint", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_INT);
|
||||
type = g_type_register_fundamental (G_TYPE_UINT, "guint", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_UINT, "guint", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_UINT);
|
||||
}
|
||||
|
||||
@@ -342,15 +393,16 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_long0_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_long0_copy, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_LONG, /* collect_type */
|
||||
value_long_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_long_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_LONG, "glong", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_LONG, "glong", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_LONG);
|
||||
type = g_type_register_fundamental (G_TYPE_ULONG, "gulong", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_ULONG, "gulong", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_ULONG);
|
||||
}
|
||||
|
||||
@@ -361,13 +413,14 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_float_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_float_copy, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_DOUBLE, /* collect_type */
|
||||
value_float_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_float_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_FLOAT, "gfloat", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_FLOAT, "gfloat", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
@@ -378,13 +431,14 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_double_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_double_copy, /* value_copy */
|
||||
NULL, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_DOUBLE, /* collect_type */
|
||||
value_double_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_double_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_DOUBLE, "gdouble", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_DOUBLE, "gdouble", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
@@ -395,15 +449,34 @@ g_value_types_init (void) /* sync with gtype.c */
|
||||
value_string_init, /* value_init */
|
||||
value_string_free_value, /* value_free */
|
||||
value_string_copy_value, /* value_copy */
|
||||
value_pointer_peek_pointer, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_POINTER, /* collect_type */
|
||||
value_string_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_string_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_STRING, "gstring", &info, &finfo);
|
||||
type = g_type_register_fundamental (G_TYPE_STRING, "gstring", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_STRING);
|
||||
}
|
||||
|
||||
/* G_TYPE_POINTER
|
||||
*/
|
||||
{
|
||||
static const GTypeValueTable value_table = {
|
||||
value_pointer_init, /* value_init */
|
||||
NULL, /* value_free */
|
||||
value_pointer_copy, /* value_copy */
|
||||
value_pointer_peek_pointer, /* value_peek_pointer */
|
||||
G_VALUE_COLLECT_POINTER, /* collect_type */
|
||||
value_pointer_collect_value, /* collect_value */
|
||||
G_VALUE_COLLECT_POINTER, /* lcopy_type */
|
||||
value_pointer_lcopy_value, /* lcopy_value */
|
||||
};
|
||||
info.value_table = &value_table;
|
||||
type = g_type_register_fundamental (G_TYPE_POINTER, "gpointer", &info, &finfo, 0);
|
||||
g_assert (type == G_TYPE_POINTER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -418,7 +491,7 @@ g_value_set_char (GValue *value,
|
||||
}
|
||||
|
||||
gint8
|
||||
g_value_get_char (GValue *value)
|
||||
g_value_get_char (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_CHAR (value), 0);
|
||||
|
||||
@@ -435,7 +508,7 @@ g_value_set_uchar (GValue *value,
|
||||
}
|
||||
|
||||
guint8
|
||||
g_value_get_uchar (GValue *value)
|
||||
g_value_get_uchar (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_UCHAR (value), 0);
|
||||
|
||||
@@ -452,7 +525,7 @@ g_value_set_boolean (GValue *value,
|
||||
}
|
||||
|
||||
gboolean
|
||||
g_value_get_boolean (GValue *value)
|
||||
g_value_get_boolean (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_BOOLEAN (value), 0);
|
||||
|
||||
@@ -469,7 +542,7 @@ g_value_set_int (GValue *value,
|
||||
}
|
||||
|
||||
gint
|
||||
g_value_get_int (GValue *value)
|
||||
g_value_get_int (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_INT (value), 0);
|
||||
|
||||
@@ -486,7 +559,7 @@ g_value_set_uint (GValue *value,
|
||||
}
|
||||
|
||||
guint
|
||||
g_value_get_uint (GValue *value)
|
||||
g_value_get_uint (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_UINT (value), 0);
|
||||
|
||||
@@ -503,7 +576,7 @@ g_value_set_long (GValue *value,
|
||||
}
|
||||
|
||||
glong
|
||||
g_value_get_long (GValue *value)
|
||||
g_value_get_long (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_LONG (value), 0);
|
||||
|
||||
@@ -520,7 +593,7 @@ g_value_set_ulong (GValue *value,
|
||||
}
|
||||
|
||||
gulong
|
||||
g_value_get_ulong (GValue *value)
|
||||
g_value_get_ulong (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_ULONG (value), 0);
|
||||
|
||||
@@ -537,7 +610,7 @@ g_value_set_float (GValue *value,
|
||||
}
|
||||
|
||||
gfloat
|
||||
g_value_get_float (GValue *value)
|
||||
g_value_get_float (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_FLOAT (value), 0);
|
||||
|
||||
@@ -554,7 +627,7 @@ g_value_set_double (GValue *value,
|
||||
}
|
||||
|
||||
gdouble
|
||||
g_value_get_double (GValue *value)
|
||||
g_value_get_double (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_DOUBLE (value), 0);
|
||||
|
||||
@@ -572,7 +645,7 @@ g_value_set_string (GValue *value,
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_value_get_string (GValue *value)
|
||||
g_value_get_string (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_STRING (value), NULL);
|
||||
|
||||
@@ -580,9 +653,26 @@ g_value_get_string (GValue *value)
|
||||
}
|
||||
|
||||
gchar*
|
||||
g_value_dup_string (GValue *value)
|
||||
g_value_dup_string (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_STRING (value), NULL);
|
||||
|
||||
return g_strdup (value->data[0].v_pointer);
|
||||
}
|
||||
|
||||
void
|
||||
g_value_set_pointer (GValue *value,
|
||||
gpointer v_pointer)
|
||||
{
|
||||
g_return_if_fail (G_IS_VALUE_POINTER (value));
|
||||
|
||||
value->data[0].v_pointer = v_pointer;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_value_get_pointer (GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_VALUE_POINTER (value), NULL);
|
||||
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
@@ -22,7 +22,7 @@
|
||||
#define __G_VALUETYPES_H__
|
||||
|
||||
|
||||
#include <gobject/gvalue.h>
|
||||
#include <gobject/gvalue.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -31,50 +31,54 @@ extern "C" {
|
||||
|
||||
|
||||
/* --- type macros --- */
|
||||
#define G_IS_VALUE_CHAR(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_CHAR))
|
||||
#define G_IS_VALUE_UCHAR(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_UCHAR))
|
||||
#define G_IS_VALUE_BOOLEAN(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_BOOLEAN))
|
||||
#define G_IS_VALUE_INT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_INT))
|
||||
#define G_IS_VALUE_UINT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_UINT))
|
||||
#define G_IS_VALUE_LONG(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_LONG))
|
||||
#define G_IS_VALUE_ULONG(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_ULONG))
|
||||
#define G_IS_VALUE_FLOAT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_FLOAT))
|
||||
#define G_IS_VALUE_DOUBLE(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_DOUBLE))
|
||||
#define G_IS_VALUE_STRING(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_STRING))
|
||||
#define G_IS_VALUE_CHAR(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_CHAR))
|
||||
#define G_IS_VALUE_UCHAR(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_UCHAR))
|
||||
#define G_IS_VALUE_BOOLEAN(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_BOOLEAN))
|
||||
#define G_IS_VALUE_INT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_INT))
|
||||
#define G_IS_VALUE_UINT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_UINT))
|
||||
#define G_IS_VALUE_LONG(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_LONG))
|
||||
#define G_IS_VALUE_ULONG(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_ULONG))
|
||||
#define G_IS_VALUE_FLOAT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_FLOAT))
|
||||
#define G_IS_VALUE_DOUBLE(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_DOUBLE))
|
||||
#define G_IS_VALUE_STRING(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_STRING))
|
||||
#define G_IS_VALUE_POINTER(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_POINTER))
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
void g_value_set_char (GValue *value,
|
||||
gint8 v_char);
|
||||
gint8 g_value_get_char (GValue *value);
|
||||
void g_value_set_uchar (GValue *value,
|
||||
guint8 v_uchar);
|
||||
guint8 g_value_get_uchar (GValue *value);
|
||||
void g_value_set_boolean (GValue *value,
|
||||
gboolean v_boolean);
|
||||
gboolean g_value_get_boolean (GValue *value);
|
||||
void g_value_set_int (GValue *value,
|
||||
gint v_int);
|
||||
gint g_value_get_int (GValue *value);
|
||||
void g_value_set_uint (GValue *value,
|
||||
guint v_uint);
|
||||
guint g_value_get_uint (GValue *value);
|
||||
void g_value_set_long (GValue *value,
|
||||
glong v_long);
|
||||
glong g_value_get_long (GValue *value);
|
||||
void g_value_set_ulong (GValue *value,
|
||||
gulong v_ulong);
|
||||
gulong g_value_get_ulong (GValue *value);
|
||||
void g_value_set_float (GValue *value,
|
||||
gfloat v_float);
|
||||
gfloat g_value_get_float (GValue *value);
|
||||
void g_value_set_double (GValue *value,
|
||||
gdouble v_double);
|
||||
gdouble g_value_get_double (GValue *value);
|
||||
void g_value_set_string (GValue *value,
|
||||
const gchar *v_string);
|
||||
gchar* g_value_get_string (GValue *value);
|
||||
gchar* g_value_dup_string (GValue *value);
|
||||
void g_value_set_char (GValue *value,
|
||||
gint8 v_char);
|
||||
gint8 g_value_get_char (const GValue *value);
|
||||
void g_value_set_uchar (GValue *value,
|
||||
guint8 v_uchar);
|
||||
guint8 g_value_get_uchar (const GValue *value);
|
||||
void g_value_set_boolean (GValue *value,
|
||||
gboolean v_boolean);
|
||||
gboolean g_value_get_boolean (const GValue *value);
|
||||
void g_value_set_int (GValue *value,
|
||||
gint v_int);
|
||||
gint g_value_get_int (const GValue *value);
|
||||
void g_value_set_uint (GValue *value,
|
||||
guint v_uint);
|
||||
guint g_value_get_uint (const GValue *value);
|
||||
void g_value_set_long (GValue *value,
|
||||
glong v_long);
|
||||
glong g_value_get_long (const GValue *value);
|
||||
void g_value_set_ulong (GValue *value,
|
||||
gulong v_ulong);
|
||||
gulong g_value_get_ulong (const GValue *value);
|
||||
void g_value_set_float (GValue *value,
|
||||
gfloat v_float);
|
||||
gfloat g_value_get_float (const GValue *value);
|
||||
void g_value_set_double (GValue *value,
|
||||
gdouble v_double);
|
||||
gdouble g_value_get_double (const GValue *value);
|
||||
void g_value_set_string (GValue *value,
|
||||
const gchar *v_string);
|
||||
gchar* g_value_get_string (const GValue *value);
|
||||
gchar* g_value_dup_string (const GValue *value);
|
||||
void g_value_set_pointer (GValue *value,
|
||||
gpointer v_pointer);
|
||||
gpointer g_value_get_pointer (GValue *value);
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user