fixed dealing with collection/lcopy of NULL values.

Mon Dec 11 04:44:11 2000  Tim Janik  <timj@gtk.org>

	* gboxed.c: fixed dealing with collection/lcopy of NULL values.

	* gclosure.h: removed insane ramblings, added G_CALLBACK() a casting
	convenience macro.

	* Makefile.am: cleanups, marshaller generation rules.

	* gmarshal.[hc]: new files with GRuntime standard marshallers.

	* glib-genmarshal.c: fix log domain, support gruntime standard
	marshallers, suport G_TYPE_PARAM, come with extern "C" and
	#include gmarshal.h.

	* glib-genmarshal.1: reflect glib-genmarshal.c updates.

	* gobject.[hc]: implement object constructor. rework parameter
	changed notification queueing, we support queue freezes now and
	don't dispatch from an idle handler anymore.
	parameter->property rename hassle.
	implemented ::properties_changed and ::notify::* signals for
	property change notification (the later supports property names
	as details). added signal connection and named data properties.
	(g_signal_connect_object): new function to setup while_alive
	connections.
	(g_object_class_install_property): sink properties now, since they
	are initially floating.
	(g_object_steal_data):
	(g_object_set_data_full):
	(g_object_set_data):
	(g_object_get_data): set/get data by using g_datalist_*() functions
	directly.
	(g_object_queue_param_changed): nuked.
	(g_object_freeze_notify): start queueing of property changes (freeze/
	thaw calls stack).
	(g_object_notify): announce changes of a certain property directly.
	(g_object_thaw_notify): process queue of property changes, therefore
	emitting GObject::notify::detail with detail being the changed
	properties names.
	(G_OBJECT_WARN_INVALID_PROPERTY_ID): saner macro variant of former
	G_WARN_INVALID_PARAM_ID().

	* gparam.[hc]: param specs are now initially floating and need to be
	sunken with g_param_spec_sink(), support G_TYPE_PARAM values.
	added G_PARAM_CONSTRUCT and G_PARAM_CONSTRUCT_ONLY parameter flags,
	required by GObjectClass.constructor().

	* gparamspecs.[hc]: added GParamSpecParam, GParamSpecPointer and
	GParamSpecCCallback, param specs for G_TYPE_PARAM, G_TYPE_POINTER
	and G_TYPE_CCALLBACK respectively.

	* gsignal.[hc]: cleanups.
	(signal_id_lookup): after walking the anchestry, try interfaces as well.
	(g_signal_new): new function to create signals from varargs type list.
	(g_signal_connect_closure): closure connection variant that works from
	signal name+detail.
	(g_signal_connect_data): c handler connection variant that works from
	signal name+detail.
	(g_signal_emit_valist): emit signal for an instance with paraneters
	collected from a va_list.
	(g_signal_emit): emit signal, taking parameters from varargs list.
	(g_signal_emit_by_name): same as g_signal_emit, working from
	signal name+detail.
	(signal_emit_R): return whether return_value needs to be altered.

	* gtype.[hc]: set log-domain to GRuntime, i'm slowly getting to all
	the points that need to reflect the upcoming rename.
	melt g_type_conforms_to() functionality into g_type_is_a(), as that
	is what we really want (liskov substitution principle).
	assorted changes to other files due to conforms_to->is_a.

	* gvalue.[hc]: implemented g_value_set_instance() that sets a value
	from an instantiatable type via the value_table's collect_value()
	function (based on an idea from James Henstridge <james@daa.com.au>).
	cleanups/fixes.

	* gvaluetypes.[hc]: implement G_TYPE_CCALLBACK and G_TYPE_PARAM.
This commit is contained in:
Tim Janik 2000-12-12 07:32:00 +00:00 committed by Tim Janik
parent cbd74878d1
commit e773d7dba6
44 changed files with 2926 additions and 1383 deletions

View File

@ -109,6 +109,7 @@ AC_ARG_ENABLE(ansi, [ --enable-ansi turn on strict ansi [default=no]]
, enable_ansi=no) , enable_ansi=no)
AC_ARG_ENABLE(threads, [ --enable-threads turn on basic thread support [default=yes] AC_ARG_ENABLE(threads, [ --enable-threads turn on basic thread support [default=yes]
([=no] will override --with-threads)],,enable_threads=yes) ([=no] will override --with-threads)],,enable_threads=yes)
AC_ARG_ENABLE(rebuilds, [ --disable-rebuilds disable all source autogeneration rules],,enable_rebuilds=yes)
if test "x$enable_threads" != "xyes"; then if test "x$enable_threads" != "xyes"; then
enable_threads=no enable_threads=no
@ -163,6 +164,21 @@ AC_PROG_CC
AM_PROG_CC_STDC AM_PROG_CC_STDC
AC_PROG_INSTALL AC_PROG_INSTALL
# define a MAINT-like variable REBUILD which is set if Perl
# and awk are found, so autogenerated sources can be rebuilt
AC_PROG_AWK
AC_CHECK_PROGS(PERL, perl5 perl)
# We would like indent, but don't require it.
AC_CHECK_PROG(INDENT, indent, indent)
REBUILD=\#
if test "x$enable_rebuilds" = "xyes" && \
test -n "$PERL" && \
$PERL -e 'exit !($] >= 5.002)' > /dev/null 2>&1 && \
test -n "$AWK" ; then
REBUILD=
fi
AC_SUBST(REBUILD)
dnl Initialize libtool dnl Initialize libtool
AM_PROG_LIBTOOL AM_PROG_LIBTOOL

View File

@ -209,25 +209,6 @@ g_array_remove_index().
@Returns: the #GArray. @Returns: the #GArray.
<!-- ##### FUNCTION g_array_sort ##### -->
<para>
</para>
@array:
@compare_func:
<!-- ##### FUNCTION g_array_sort_with_data ##### -->
<para>
</para>
@array:
@compare_func:
@user_data:
<!-- ##### MACRO g_array_index ##### --> <!-- ##### MACRO g_array_index ##### -->
<para> <para>
Returns the element of a #GArray at the given index. Returns the element of a #GArray at the given index.

View File

@ -123,25 +123,6 @@ g_byte_array_remove_index().
@Returns: the #GByteArray. @Returns: the #GByteArray.
<!-- ##### FUNCTION g_byte_array_sort ##### -->
<para>
</para>
@array:
@compare_func:
<!-- ##### FUNCTION g_byte_array_sort_with_data ##### -->
<para>
</para>
@array:
@compare_func:
@user_data:
<!-- ##### FUNCTION g_byte_array_set_size ##### --> <!-- ##### FUNCTION g_byte_array_set_size ##### -->
<para> <para>
Sets the size of the #GByteArray, expanding it if necessary. Sets the size of the #GByteArray, expanding it if necessary.

View File

@ -156,25 +156,6 @@ g_ptr_array_remove_index().
@Returns: the pointer which was removed. @Returns: the pointer which was removed.
<!-- ##### FUNCTION g_ptr_array_sort ##### -->
<para>
</para>
@array:
@compare_func:
<!-- ##### FUNCTION g_ptr_array_sort_with_data ##### -->
<para>
</para>
@array:
@compare_func:
@user_data:
<!-- ##### FUNCTION g_ptr_array_set_size ##### --> <!-- ##### FUNCTION g_ptr_array_set_size ##### -->
<para> <para>
Sets the size of the array, expanding it if necessary. Sets the size of the array, expanding it if necessary.

View File

@ -51,11 +51,11 @@ called by g_cache_remove() when the object is no longer needed (i.e. its
reference count drops to 0). reference count drops to 0).
@hash_key_func: a function to create a hash value from a key. @hash_key_func: a function to create a hash value from a key.
@hash_value_func: a function to create a hash value from a value. @hash_value_func: a function to create a hash value from a value.
@key_equal_func: a function to compare two keys. It should return TRUE if @key_compare_func:
the two keys are equivalent.
@Returns: a new #GCache. @Returns: a new #GCache.
<!-- # Unused Parameters # --> <!-- # Unused Parameters # -->
@key_compare_func: @key_equal_func: a function to compare two keys. It should return TRUE if
the two keys are equivalent.
<!-- ##### FUNCTION g_cache_insert ##### --> <!-- ##### FUNCTION g_cache_insert ##### -->

View File

@ -47,7 +47,6 @@ g_completion_complete().
@func: @func:
@prefix: @prefix:
@cache: @cache:
@strncmp_func:
<!-- ##### FUNCTION g_completion_new ##### --> <!-- ##### FUNCTION g_completion_new ##### -->
<para> <para>
@ -71,16 +70,6 @@ This is used when you use data structures as #GCompletion items.
@Returns: the string corresponding to the item. @Returns: the string corresponding to the item.
<!-- ##### USER_FUNCTION GCompletionStrcmpFunc ##### -->
<para>
</para>
@s1:
@s2:
@Returns:
<!-- ##### FUNCTION g_completion_add_items ##### --> <!-- ##### FUNCTION g_completion_add_items ##### -->
<para> <para>
Adds items to the #GCompletion. Adds items to the #GCompletion.

View File

@ -52,56 +52,15 @@ Character Set Conversion
<!-- ##### FUNCTION g_iconv_open ##### -->
<para>
</para>
@to_codeset:
@from_codeset:
@Returns:
<!-- ##### FUNCTION g_iconv ##### -->
<para>
</para>
@converter:
@inbuf:
@inbytes_left:
@outbuf:
@outbytes_left:
@Returns:
<!-- ##### FUNCTION g_iconv_close ##### -->
<para>
</para>
@converter:
@Returns:
<!-- ##### FUNCTION g_locale_to_utf8 ##### -->
<para>
</para>
@opsysstring:
@error:
@Returns:
<!-- ##### FUNCTION g_filename_to_utf8 ##### --> <!-- ##### FUNCTION g_filename_to_utf8 ##### -->
<para> <para>
</para> </para>
@opsysstring: @opsysstring:
@error:
@Returns: @Returns:
<!-- # Unused Parameters # -->
@error:
<!-- ##### FUNCTION g_filename_from_utf8 ##### --> <!-- ##### FUNCTION g_filename_from_utf8 ##### -->
@ -110,18 +69,9 @@ Character Set Conversion
</para> </para>
@utf8string: @utf8string:
@error:
@Returns: @Returns:
<!-- # Unused Parameters # -->
<!-- ##### FUNCTION g_locale_from_utf8 ##### -->
<para>
</para>
@utf8string:
@error: @error:
@Returns:
<!-- ##### ENUM GConvertError ##### --> <!-- ##### ENUM GConvertError ##### -->
@ -132,5 +82,4 @@ Character Set Conversion
@G_CONVERT_ERROR_NO_CONVERSION: @G_CONVERT_ERROR_NO_CONVERSION:
@G_CONVERT_ERROR_ILLEGAL_SEQUENCE: @G_CONVERT_ERROR_ILLEGAL_SEQUENCE:
@G_CONVERT_ERROR_FAILED: @G_CONVERT_ERROR_FAILED:
@G_CONVERT_ERROR_PARTIAL_INPUT:

View File

@ -93,23 +93,3 @@ File Utilities
@Returns: @Returns:
<!-- ##### FUNCTION g_mkstemp ##### -->
<para>
</para>
@tmpl:
@Returns:
<!-- ##### FUNCTION g_file_open_tmp ##### -->
<para>
</para>
@tmpl:
@name_used:
@error:
@Returns:

View File

@ -1,24 +1,61 @@
<!-- ##### FUNCTION g_main_remove_poll ##### --> <!-- ##### FUNCTION g_markup_parse_context_parse ##### -->
<para>
Removes a file descriptor from the list being polled.
</para>
@fd: the #GPollFD to remove.
<!-- ##### MACRO lseek ##### -->
<para>
</para>
<!-- ##### FUNCTION g_convert_error_quark ##### -->
<para> <para>
</para> </para>
@context:
@text:
@text_len:
@error:
@Returns: @Returns:
<!-- ##### MACRO write ##### --> <!-- ##### STRUCT GSource ##### -->
<para>
</para>
<!-- ##### FUNCTION g_source_connect_indirect ##### -->
<para>
</para>
@source:
@callback_data:
@callback_funcs:
<!-- ##### FUNCTION g_locale_to_utf8 ##### -->
<para>
</para>
@opsysstring:
@error:
@Returns:
<!-- ##### FUNCTION g_iconv_close ##### -->
<para>
</para>
@converter:
@Returns:
<!-- ##### MACRO popen ##### -->
<para>
</para>
<!-- ##### FUNCTION g_source_set_can_recurse ##### -->
<para>
</para>
@source:
@can_recurse:
<!-- ##### MACRO pclose ##### -->
<para> <para>
</para> </para>
@ -40,26 +77,122 @@ the results may be needed.
See #G_PRIORITY_DEFAULT, #G_PRIORITY_DEFAULT_IDLE, #G_PRIORITY_HIGH, See #G_PRIORITY_DEFAULT, #G_PRIORITY_DEFAULT_IDLE, #G_PRIORITY_HIGH,
#G_PRIORITY_HIGH_IDLE, and #G_PRIORITY_LOW. #G_PRIORITY_HIGH_IDLE, and #G_PRIORITY_LOW.
<!-- ##### MACRO pclose ##### --> <!-- ##### ENUM GMarkupError ##### -->
<para>
</para>
@G_MARKUP_ERROR_BAD_UTF8: text being parsed was not valid UTF-8
@G_MARKUP_ERROR_EMPTY: document contained nothing, or only whitespace
@G_MARKUP_ERROR_PARSE: document was ill-formed
@G_MARKUP_ERROR_UNKNOWN_ELEMENT: error should be set by #GMarkupParser functions; element wasn't known
@G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE: error should be set by #GMarkupParser functions; attribute wasn't known
@G_MARKUP_ERROR_INVALID_CONTENT: error should be set by #GMarkupParser functions; something was wrong with contents of the document, e.g. invalid attribute value
<!-- ##### FUNCTION g_main_context_add_poll ##### -->
<para>
</para>
@context:
@fd:
@priority:
<!-- ##### MACRO lseek ##### -->
<para> <para>
</para> </para>
<!-- ##### MACRO g_string ##### --> <!-- ##### FUNCTION g_string_new_len ##### -->
<para> <para>
Turns the argument into a string literal by using the '#' stringizing operator.
</para> </para>
@x: text to convert to a literal string. @init:
@len:
@Returns:
<!-- ##### MACRO popen ##### --> <!-- ##### STRUCT GSourceCallbackFuncs ##### -->
<para>
</para>
@ref:
@unref:
@get:
<!-- ##### FUNCTION g_array_sort ##### -->
<para>
</para>
@array:
@compare_func:
<!-- ##### FUNCTION g_main_context_find_source_by_funcs_user_data ##### -->
<para>
</para>
@context:
@funcs:
@user_data:
@Returns:
@source_data:
<!-- ##### FUNCTION g_markup_parse_context_free ##### -->
<para>
</para>
@context:
<!-- ##### STRUCT GMarkupParseContext ##### -->
<para> <para>
</para> </para>
<!-- ##### MACRO access ##### --> <!-- ##### FUNCTION g_ptr_array_sort ##### -->
<para>
</para>
@array:
@compare_func:
<!-- ##### FUNCTION g_main_context_query ##### -->
<para>
</para>
@context:
@max_priority:
@timeout:
@fds:
@n_fds:
@Returns:
<!-- ##### FUNCTION g_iconv_open ##### -->
<para>
</para>
@to_codeset:
@from_codeset:
@Returns:
<!-- ##### FUNCTION g_source_new ##### -->
<para>
</para>
@source_funcs:
@struct_size:
@Returns:
<!-- ##### MACRO getpid ##### -->
<para> <para>
</para> </para>
@ -78,17 +211,43 @@ priority are stored in the order in which they were added.
type of source. type of source.
@Returns: TRUE if an event source was found and removed. @Returns: TRUE if an event source was found and removed.
<!-- ##### MACRO open ##### --> <!-- ##### MACRO close ##### -->
<para> <para>
</para> </para>
<!-- ##### MACRO getpid ##### --> <!-- ##### FUNCTION g_source_get_id ##### -->
<para> <para>
</para> </para>
@source:
@Returns:
<!-- ##### FUNCTION g_mkstemp ##### -->
<para>
</para>
@tmpl:
@Returns:
<!-- ##### FUNCTION g_main_context_get_poll_func ##### -->
<para>
</para>
@context:
@Returns:
<!-- ##### FUNCTION g_source_add_poll ##### -->
<para>
</para>
@source:
@fd:
<!-- ##### MACRO fdopen ##### --> <!-- ##### MACRO fdopen ##### -->
<para> <para>
@ -96,11 +255,240 @@ type of source.
</para> </para>
<!-- ##### MACRO close ##### --> <!-- ##### FUNCTION g_source_get_current_time ##### -->
<para> <para>
</para> </para>
@source:
@timeval:
<!-- ##### USER_FUNCTION GCompletionStrcmpFunc ##### -->
<para>
</para>
@s1:
@s2:
@Returns:
<!-- ##### FUNCTION g_main_loop_new ##### -->
<para>
</para>
@context:
@is_running:
@Returns:
<!-- ##### FUNCTION g_iconv ##### -->
<para>
</para>
@converter:
@inbuf:
@inbytes_left:
@outbuf:
@outbytes_left:
@Returns:
<!-- ##### FUNCTION g_source_ref ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_byte_array_sort ##### -->
<para>
</para>
@array:
@compare_func:
<!-- ##### FUNCTION g_markup_parse_context_get_position ##### -->
<para>
</para>
@context:
@line_number:
@char_number:
<!-- ##### FUNCTION g_locale_from_utf8 ##### -->
<para>
</para>
@utf8string:
@error:
@Returns:
<!-- ##### FUNCTION g_main_loop_is_running ##### -->
<para>
</para>
@loop:
@Returns:
<!-- ##### FUNCTION g_main_context_remove_poll ##### -->
<para>
</para>
@context:
@fd:
<!-- ##### FUNCTION g_byte_array_sort_with_data ##### -->
<para>
</para>
@array:
@compare_func:
@user_data:
<!-- ##### FUNCTION g_markup_parse_context_new ##### -->
<para>
</para>
@parser:
@flags:
@user_data:
@user_data_dnotify:
@Returns:
<!-- ##### FUNCTION g_source_get_can_recurse ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_main_context_get ##### -->
<para>
</para>
@thread:
@Returns:
<!-- ##### FUNCTION g_source_remove_poll ##### -->
<para>
</para>
@source:
@fd:
<!-- ##### FUNCTION g_tree_new_with_data ##### -->
<para>
</para>
@key_compare_func:
@user_data:
@Returns:
<!-- ##### FUNCTION g_source_get_priority ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_source_connect ##### -->
<para>
</para>
@source:
@func:
@data:
@notify:
<!-- ##### FUNCTION g_main_context_iteration ##### -->
<para>
</para>
@context:
@may_block:
@Returns:
<!-- ##### FUNCTION g_main_context_dispatch ##### -->
<para>
</para>
@context:
<!-- ##### FUNCTION g_main_loop_quit ##### -->
<para>
</para>
@loop:
<!-- ##### FUNCTION g_main_context_prepare ##### -->
<para>
</para>
@context:
@priority:
@Returns:
<!-- ##### FUNCTION g_source_set_priority ##### -->
<para>
</para>
@source:
@priority:
<!-- ##### FUNCTION g_ptr_array_sort_with_data ##### -->
<para>
</para>
@array:
@compare_func:
@user_data:
<!-- ##### FUNCTION g_list_sort_with_data ##### -->
<para>
</para>
@list:
@compare_func:
@user_data:
@Returns:
<!-- ##### FUNCTION g_main_context_find_source_by_user_data ##### -->
<para>
</para>
@context:
@user_data:
@Returns:
<!-- ##### FUNCTION g_main_context_set_poll_func ##### -->
<para>
</para>
@context:
@func:
<!-- ##### MACRO getcwd ##### --> <!-- ##### MACRO getcwd ##### -->
<para> <para>
@ -108,11 +496,71 @@ type of source.
</para> </para>
<!-- ##### MACRO read ##### --> <!-- ##### FUNCTION g_io_create_watch ##### -->
<para> <para>
</para> </para>
@channel:
@condition:
@Returns:
<!-- ##### FUNCTION g_source_unref ##### -->
<para>
</para>
@source:
<!-- ##### MACRO write ##### -->
<para>
</para>
<!-- ##### FUNCTION g_main_context_find_source_by_id ##### -->
<para>
</para>
@context:
@id:
@Returns:
<!-- ##### FUNCTION g_main_remove_poll ##### -->
<para>
Removes a file descriptor from the list being polled.
</para>
@fd: the #GPollFD to remove.
<!-- ##### MACRO access ##### -->
<para>
</para>
<!-- ##### MACRO g_string ##### -->
<para>
Turns the argument into a string literal by using the '#' stringizing operator.
</para>
@x: text to convert to a literal string.
<!-- ##### FUNCTION g_idle_source_new ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_main_context_pending ##### -->
<para>
</para>
@context:
@Returns:
<!-- ##### FUNCTION g_main_win32_get_poll_func ##### --> <!-- ##### FUNCTION g_main_win32_get_poll_func ##### -->
<para> <para>
@ -121,3 +569,175 @@ type of source.
@Returns: @Returns:
<!-- ##### FUNCTION g_main_loop_run ##### -->
<para>
</para>
@loop:
<!-- ##### MACRO read ##### -->
<para>
</para>
<!-- ##### FUNCTION g_array_sort_with_data ##### -->
<para>
</para>
@array:
@compare_func:
@user_data:
<!-- ##### MACRO G_MARKUP_ERROR ##### -->
<para>
</para>
<!-- ##### FUNCTION g_main_context_default ##### -->
<para>
</para>
@Returns:
<!-- ##### ENUM GMarkupParseFlags ##### -->
<para>
There are no flags right now
</para>
@G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG:
<!-- ##### FUNCTION g_slist_sort_with_data ##### -->
<para>
</para>
@list:
@compare_func:
@user_data:
@Returns:
<!-- ##### FUNCTION g_markup_parse_context_end_parse ##### -->
<para>
</para>
@context:
@error:
@Returns:
<!-- ##### FUNCTION g_source_get_context ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_timeout_source_new ##### -->
<para>
</para>
@interval:
@Returns:
<!-- ##### STRUCT GMarkupParser ##### -->
<para>
Any of the fields in #GMarkupParser can be %NULL, in which case they
will be ignored. Except for the @error function, any of these
callbacks can set an error; in particular the
%G_MARKUP_ERROR_UNKNOWN_ELEMENT, %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
and %G_MARKUP_ERROR_INVALID_CONTENT errors are intended to be set
from these callbacks. If you set an error from a callback,
g_markup_parse_context_parse() will report that error back to its caller.
</para>
@start_element: Callback to invoke when the opening tag of an element
is seen.
@end_element: Callback to invoke when the closing tag of an element is seen
@text: Callback to invoke when some text is seen (text is always
inside an element)
@passthrough: Callback to invoke for comments and processing
instructions; if you're re-writing the parsed document, write the
passthrough text back out in the same position
@error: Callback to invoke when an error occurs
<!-- ##### USER_FUNCTION GEqualFunc ##### -->
<para>
Specifies the type of a function used to test two values for
equality. The function should return TRUE if both values are equal and
FALSE otherwise.
</para>
@a: a value.
@b: a value to compare with.
@Returns: TRUE if @a = @b; FALSE otherwise.
<!-- ##### FUNCTION g_main_loop_destroy ##### -->
<para>
</para>
@loop:
<!-- ##### FUNCTION g_file_open_tmp ##### -->
<para>
</para>
@tmpl:
@name_used:
@error:
@Returns:
<!-- ##### STRUCT GMainContext ##### -->
<para>
</para>
<!-- ##### FUNCTION g_main_context_check ##### -->
<para>
</para>
@context:
@max_priority:
@fds:
@n_fds:
@Returns:
<!-- ##### FUNCTION g_convert_error_quark ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_source_destroy ##### -->
<para>
</para>
@source:
<!-- ##### FUNCTION g_markup_escape_text ##### -->
<para>
</para>
@text:
@length:
@Returns:
<!-- ##### MACRO open ##### -->
<para>
</para>

View File

@ -69,15 +69,15 @@ Hash values are used to determine where keys are stored within the
#GHashTable data structure. #GHashTable data structure.
The g_direct_hash(), g_int_hash() and g_str_hash() functions are provided for The g_direct_hash(), g_int_hash() and g_str_hash() functions are provided for
some common types of keys. If hash_func is NULL, g_direct_hash() is used. some common types of keys. If hash_func is NULL, g_direct_hash() is used.
@key_compare_func:
@Returns: a new #GHashTable.
<!-- # Unused Parameters # -->
@key_equal_func: a function to check two keys for equality. This is @key_equal_func: a function to check two keys for equality. This is
used when looking up keys in the #GHashTable. The g_direct_equal(), used when looking up keys in the #GHashTable. The g_direct_equal(),
g_int_equal() and g_str_equal() functions are provided for the most g_int_equal() and g_str_equal() functions are provided for the most
common types of keys. If @key_equal_func is NULL, keys are compared common types of keys. If @key_equal_func is NULL, keys are compared
directly in a similar fashion to g_direct_equal(), but without the directly in a similar fashion to g_direct_equal(), but without the
overhead of a function call. overhead of a function call.
@Returns: a new #GHashTable.
<!-- # Unused Parameters # -->
@key_compare_func:
<!-- ##### USER_FUNCTION GHashFunc ##### --> <!-- ##### USER_FUNCTION GHashFunc ##### -->
@ -104,18 +104,6 @@ lookup.
@Returns: the hash value corresponding to the key. @Returns: the hash value corresponding to the key.
<!-- ##### USER_FUNCTION GEqualFunc ##### -->
<para>
Specifies the type of a function used to test two values for
equality. The function should return TRUE if both values are equal and
FALSE otherwise.
</para>
@a: a value.
@b: a value to compare with.
@Returns: TRUE if @a = @b; FALSE otherwise.
<!-- ##### FUNCTION g_hash_table_insert ##### --> <!-- ##### FUNCTION g_hash_table_insert ##### -->
<para> <para>
Inserts a new key and value into a #GHashTable. Inserts a new key and value into a #GHashTable.

View File

@ -209,16 +209,6 @@ Decrements the reference count of a #GIOChannel.
@channel: a #GIOChannel. @channel: a #GIOChannel.
<!-- ##### FUNCTION g_io_create_watch ##### -->
<para>
</para>
@channel:
@condition:
@Returns:
<!-- ##### FUNCTION g_io_add_watch ##### --> <!-- ##### FUNCTION g_io_add_watch ##### -->
<para> <para>
Adds the #GIOChannel into the Adds the #GIOChannel into the
@ -324,6 +314,6 @@ generic way.
@io_write: @io_write:
@io_seek: @io_seek:
@io_close: @io_close:
@io_create_watch: @io_add_watch:
@io_free: @io_free:

View File

@ -268,17 +268,6 @@ value if the first element comes after the second.
@Returns: the start of the sorted #GList. @Returns: the start of the sorted #GList.
<!-- ##### FUNCTION g_list_sort_with_data ##### -->
<para>
</para>
@list:
@compare_func:
@user_data:
@Returns:
<!-- ##### USER_FUNCTION GCompareFunc ##### --> <!-- ##### USER_FUNCTION GCompareFunc ##### -->
<para> <para>
Specifies the type of a comparison function used to compare two Specifies the type of a comparison function used to compare two

View File

@ -271,17 +271,6 @@ value if the first element comes after the second.
@Returns: the start of the sorted #GList. @Returns: the start of the sorted #GList.
<!-- ##### FUNCTION g_slist_sort_with_data ##### -->
<para>
</para>
@list:
@compare_func:
@user_data:
@Returns:
<!-- ##### FUNCTION g_slist_concat ##### --> <!-- ##### FUNCTION g_slist_concat ##### -->
<para> <para>
Adds the second #GSList onto the end of the first #GSList. Adds the second #GSList onto the end of the first #GSList.

View File

@ -96,6 +96,7 @@ manages all available sources of events.
<graphic fileref="mainloop-states.gif" format="gif"></graphic> <graphic fileref="mainloop-states.gif" format="gif"></graphic>
</figure> </figure>
</refsect2> </refsect2>
<!-- ##### SECTION See_Also ##### --> <!-- ##### SECTION See_Also ##### -->
<para> <para>
@ -108,50 +109,7 @@ of a GLib or GTK+ application.
</para> </para>
<!-- ##### FUNCTION g_main_loop_new ##### --> <!-- ##### FUNCTION g_main_new ##### -->
<para>
</para>
@context:
@is_running:
@Returns:
<!-- ##### FUNCTION g_main_loop_destroy ##### -->
<para>
</para>
@loop:
<!-- ##### FUNCTION g_main_loop_run ##### -->
<para>
</para>
@loop:
<!-- ##### FUNCTION g_main_loop_quit ##### -->
<para>
</para>
@loop:
<!-- ##### FUNCTION g_main_loop_is_running ##### -->
<para>
</para>
@loop:
@Returns:
<!-- ##### MACRO g_main_new ##### -->
<para> <para>
Creates a new #GMainLoop for the default main loop. A compatibility Creates a new #GMainLoop for the default main loop. A compatibility
macro, see g_main_loop_new(). macro, see g_main_loop_new().
@ -162,7 +120,7 @@ very important since calling g_main_run() will set this to TRUE anyway.
@Returns: a new #GMainLoop. @Returns: a new #GMainLoop.
<!-- ##### MACRO g_main_destroy ##### --> <!-- ##### FUNCTION g_main_destroy ##### -->
<para> <para>
Frees the memory allocated for the #GMainLoop. A compatibility macro, see Frees the memory allocated for the #GMainLoop. A compatibility macro, see
g_main_loop_destroy(). g_main_loop_destroy().
@ -171,7 +129,7 @@ g_main_loop_destroy().
@loop: a #GMainLoop. @loop: a #GMainLoop.
<!-- ##### MACRO g_main_run ##### --> <!-- ##### FUNCTION g_main_run ##### -->
<para> <para>
Runs a main loop until it stops running. A compatibility macro, see g_main_loop_run(). Runs a main loop until it stops running. A compatibility macro, see g_main_loop_run().
</para> </para>
@ -179,7 +137,7 @@ Runs a main loop until it stops running. A compatibility macro, see g_main_loop_
@loop: a #GMainLoop. @loop: a #GMainLoop.
<!-- ##### MACRO g_main_quit ##### --> <!-- ##### FUNCTION g_main_quit ##### -->
<para> <para>
Stops the #GMainLoop. If g_main_run() was called to run the #GMainLoop, Stops the #GMainLoop. If g_main_run() was called to run the #GMainLoop,
it will now return. A compatibility macro, see g_main_loop_quit(). it will now return. A compatibility macro, see g_main_loop_quit().
@ -188,7 +146,7 @@ it will now return. A compatibility macro, see g_main_loop_quit().
@loop: a #GMainLoop. @loop: a #GMainLoop.
<!-- ##### MACRO g_main_is_running ##### --> <!-- ##### FUNCTION g_main_is_running ##### -->
<para> <para>
Checks if the main loop is running. A compatibility macro, see Checks if the main loop is running. A compatibility macro, see
g_main_loop_is_running(). g_main_loop_is_running().
@ -243,40 +201,7 @@ It is not used within GLib or GTK+.
<!-- ##### STRUCT GMainContext ##### --> <!-- ##### FUNCTION g_main_iteration ##### -->
<para>
</para>
<!-- ##### FUNCTION g_main_context_get ##### -->
<para>
</para>
@thread:
@Returns:
<!-- ##### FUNCTION g_main_context_default ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_main_context_iteration ##### -->
<para>
</para>
@context:
@may_block:
@Returns:
<!-- ##### MACRO g_main_iteration ##### -->
<para> <para>
Runs a single iteration for the default #GMainContext. Runs a single iteration for the default #GMainContext.
A compatibility macro, see g_main_context_iteration(). A compatibility macro, see g_main_context_iteration().
@ -289,16 +214,7 @@ processed.
@Returns: TRUE if more events are pending. @Returns: TRUE if more events are pending.
<!-- ##### FUNCTION g_main_context_pending ##### --> <!-- ##### FUNCTION g_main_pending ##### -->
<para>
</para>
@context:
@Returns:
<!-- ##### MACRO g_main_pending ##### -->
<para> <para>
Checks if any events are pending for the default #GMainContext Checks if any events are pending for the default #GMainContext
(i.e. ready to be processed). A compatibility macro, see (i.e. ready to be processed). A compatibility macro, see
@ -308,100 +224,6 @@ g_main_context_pending().
@Returns: %TRUE if any events are pending. @Returns: %TRUE if any events are pending.
<!-- ##### FUNCTION g_main_context_find_source_by_id ##### -->
<para>
</para>
@context:
@id:
@Returns:
<!-- ##### FUNCTION g_main_context_find_source_by_user_data ##### -->
<para>
</para>
@context:
@user_data:
@Returns:
<!-- ##### FUNCTION g_main_context_find_source_by_funcs_user_data ##### -->
<para>
</para>
@context:
@funcs:
@user_data:
@Returns:
<!-- # Unused Parameters # -->
@source_data:
<!-- ##### FUNCTION g_main_context_prepare ##### -->
<para>
</para>
@context:
@priority:
@Returns:
<!-- ##### FUNCTION g_main_context_query ##### -->
<para>
</para>
@context:
@max_priority:
@timeout:
@fds:
@n_fds:
@Returns:
<!-- ##### FUNCTION g_main_context_check ##### -->
<para>
</para>
@context:
@max_priority:
@fds:
@n_fds:
@Returns:
<!-- ##### FUNCTION g_main_context_dispatch ##### -->
<para>
</para>
@context:
<!-- ##### FUNCTION g_main_context_set_poll_func ##### -->
<para>
</para>
@context:
@func:
<!-- ##### FUNCTION g_main_context_get_poll_func ##### -->
<para>
</para>
@context:
@Returns:
<!-- ##### USER_FUNCTION GPollFunc ##### --> <!-- ##### USER_FUNCTION GPollFunc ##### -->
<para> <para>
Specifies the type of function passed to g_main_set_poll_func(). Specifies the type of function passed to g_main_set_poll_func().
@ -417,26 +239,7 @@ The semantics of the function should match those of the
or -1 if an error occurred. or -1 if an error occurred.
<!-- ##### FUNCTION g_main_context_add_poll ##### --> <!-- ##### FUNCTION g_main_set_poll_func ##### -->
<para>
</para>
@context:
@fd:
@priority:
<!-- ##### FUNCTION g_main_context_remove_poll ##### -->
<para>
</para>
@context:
@fd:
<!-- ##### MACRO g_main_set_poll_func ##### -->
<para> <para>
Sets the function to use for the handle polling of file descriptors Sets the function to use for the handle polling of file descriptors
for the default main context. This is a compatability macro, see for the default main context. This is a compatability macro, see
@ -446,15 +249,6 @@ g_main_context_set_poll_func() for full details.
@func: the function to call to poll all file descriptors. @func: the function to call to poll all file descriptors.
<!-- ##### FUNCTION g_timeout_source_new ##### -->
<para>
</para>
@interval:
@Returns:
<!-- ##### FUNCTION g_timeout_add ##### --> <!-- ##### FUNCTION g_timeout_add ##### -->
<para> <para>
</para> </para>
@ -477,14 +271,6 @@ g_main_context_set_poll_func() for full details.
@Returns: @Returns:
<!-- ##### FUNCTION g_idle_source_new ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_idle_add ##### --> <!-- ##### FUNCTION g_idle_add ##### -->
<para> <para>
</para> </para>
@ -501,10 +287,10 @@ g_main_context_set_poll_func() for full details.
@priority: @priority:
@function: @function:
@data: @data:
@notify: @destroy:
@Returns: @Returns:
<!-- # Unused Parameters # --> <!-- # Unused Parameters # -->
@destroy: @notify:
<!-- ##### FUNCTION g_idle_remove_by_data ##### --> <!-- ##### FUNCTION g_idle_remove_by_data ##### -->
@ -550,12 +336,6 @@ poll() function to indicate which events occurred.
@events: @events:
@revents: @revents:
<!-- ##### STRUCT GSource ##### -->
<para>
</para>
<!-- ##### STRUCT GSourceFuncs ##### --> <!-- ##### STRUCT GSourceFuncs ##### -->
<para> <para>
The #GSourceFuncs struct contains a table of functions used to handle The #GSourceFuncs struct contains a table of functions used to handle
@ -636,122 +416,20 @@ the required condition has been met, and returns TRUE if so.
@dispatch: @dispatch:
@destroy: @destroy:
<!-- ##### STRUCT GSourceCallbackFuncs ##### -->
<para>
</para>
@ref:
@unref:
@get:
<!-- ##### FUNCTION g_source_new ##### -->
<para>
</para>
@source_funcs:
@struct_size:
@Returns:
<!-- ##### FUNCTION g_source_ref ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_source_unref ##### -->
<para>
</para>
@source:
<!-- ##### FUNCTION g_source_add ##### --> <!-- ##### FUNCTION g_source_add ##### -->
<para> <para>
</para> </para>
@priority:
@can_recurse:
@funcs:
@source_data:
@user_data:
@notify:
@Returns:
<!-- # Unused Parameters # -->
@source: @source:
@context: @context:
@Returns:
<!-- ##### FUNCTION g_source_destroy ##### -->
<para>
</para>
@source:
<!-- ##### FUNCTION g_source_set_priority ##### -->
<para>
</para>
@source:
@priority:
<!-- ##### FUNCTION g_source_get_priority ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_source_set_can_recurse ##### -->
<para>
</para>
@source:
@can_recurse:
<!-- ##### FUNCTION g_source_get_can_recurse ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_source_get_id ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_source_get_context ##### -->
<para>
</para>
@source:
@Returns:
<!-- ##### FUNCTION g_source_connect ##### -->
<para>
</para>
@source:
@func:
@data:
@notify:
<!-- ##### USER_FUNCTION GSourceFunc ##### --> <!-- ##### USER_FUNCTION GSourceFunc ##### -->
@ -765,43 +443,6 @@ of the above functions.
@Returns: it should return FALSE if the source should be removed. @Returns: it should return FALSE if the source should be removed.
<!-- ##### FUNCTION g_source_connect_indirect ##### -->
<para>
</para>
@source:
@callback_data:
@callback_funcs:
<!-- ##### FUNCTION g_source_add_poll ##### -->
<para>
</para>
@source:
@fd:
<!-- ##### FUNCTION g_source_remove_poll ##### -->
<para>
</para>
@source:
@fd:
<!-- ##### FUNCTION g_source_get_current_time ##### -->
<para>
</para>
@source:
@timeval:
<!-- ##### FUNCTION g_source_remove ##### --> <!-- ##### FUNCTION g_source_remove ##### -->
<para> <para>
</para> </para>

View File

@ -87,118 +87,3 @@ Character references
</para> </para>
<!-- ##### ENUM GMarkupError ##### -->
<para>
</para>
@G_MARKUP_ERROR_BAD_UTF8: text being parsed was not valid UTF-8
@G_MARKUP_ERROR_EMPTY: document contained nothing, or only whitespace
@G_MARKUP_ERROR_PARSE: document was ill-formed
@G_MARKUP_ERROR_UNKNOWN_ELEMENT: error should be set by #GMarkupParser functions; element wasn't known
@G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE: error should be set by #GMarkupParser functions; attribute wasn't known
@G_MARKUP_ERROR_INVALID_CONTENT: error should be set by #GMarkupParser functions; something was wrong with contents of the document, e.g. invalid attribute value
<!-- ##### MACRO G_MARKUP_ERROR ##### -->
<para>
</para>
<!-- ##### ENUM GMarkupParseFlags ##### -->
<para>
There are no flags right now
</para>
@G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG:
<!-- ##### STRUCT GMarkupParseContext ##### -->
<para>
</para>
<!-- ##### STRUCT GMarkupParser ##### -->
<para>
Any of the fields in #GMarkupParser can be %NULL, in which case they
will be ignored. Except for the @error function, any of these
callbacks can set an error; in particular the
%G_MARKUP_ERROR_UNKNOWN_ELEMENT, %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
and %G_MARKUP_ERROR_INVALID_CONTENT errors are intended to be set
from these callbacks. If you set an error from a callback,
g_markup_parse_context_parse() will report that error back to its caller.
</para>
@start_element: Callback to invoke when the opening tag of an element
is seen.
@end_element: Callback to invoke when the closing tag of an element is seen
@text: Callback to invoke when some text is seen (text is always
inside an element)
@passthrough: Callback to invoke for comments and processing
instructions; if you're re-writing the parsed document, write the
passthrough text back out in the same position
@error: Callback to invoke when an error occurs
<!-- ##### FUNCTION g_markup_escape_text ##### -->
<para>
</para>
@text:
@length:
@Returns:
<!-- ##### FUNCTION g_markup_parse_context_end_parse ##### -->
<para>
</para>
@context:
@error:
@Returns:
<!-- ##### FUNCTION g_markup_parse_context_free ##### -->
<para>
</para>
@context:
<!-- ##### FUNCTION g_markup_parse_context_get_position ##### -->
<para>
</para>
@context:
@line_number:
@char_number:
<!-- ##### FUNCTION g_markup_parse_context_new ##### -->
<para>
</para>
@parser:
@flags:
@user_data:
@user_data_dnotify:
@Returns:
<!-- ##### FUNCTION g_markup_parse_context_parse ##### -->
<para>
</para>
@context:
@text:
@text_len:
@error:
@Returns:

View File

@ -83,9 +83,9 @@ Note that this must be called before any records are added to the #GRelation.
@relation: a #GRelation. @relation: a #GRelation.
@field: the field to index, counting from 0. @field: the field to index, counting from 0.
@hash_func: a function to produce a hash value from the field data. @hash_func: a function to produce a hash value from the field data.
@key_equal_func: a function to compare two values of the given field.
<!-- # Unused Parameters # -->
@key_compare_func: @key_compare_func:
<!-- # Unused Parameters # -->
@key_equal_func: a function to compare two values of the given field.
<!-- ##### FUNCTION g_relation_insert ##### --> <!-- ##### FUNCTION g_relation_insert ##### -->

View File

@ -36,13 +36,13 @@ Shell-related Utilities
</para> </para>
@command_line: @command_line:
@argcp: @argc:
@argvp: @argv:
@error: @error:
@Returns: @Returns:
<!-- # Unused Parameters # --> <!-- # Unused Parameters # -->
@argc: @argcp:
@argv: @argvp:
<!-- ##### FUNCTION g_shell_quote ##### --> <!-- ##### FUNCTION g_shell_quote ##### -->

View File

@ -45,16 +45,6 @@ Creates a new #GString, initialized with the given string.
@Returns: the new #GString. @Returns: the new #GString.
<!-- ##### FUNCTION g_string_new_len ##### -->
<para>
</para>
@init:
@len:
@Returns:
<!-- ##### FUNCTION g_string_sized_new ##### --> <!-- ##### FUNCTION g_string_sized_new ##### -->
<para> <para>
Creates a new GString, with enough space for @dfl_size characters. Creates a new GString, with enough space for @dfl_size characters.

View File

@ -61,16 +61,6 @@ second.
@Returns: a new #GTree. @Returns: a new #GTree.
<!-- ##### FUNCTION g_tree_new_with_data ##### -->
<para>
</para>
@key_compare_func:
@user_data:
@Returns:
<!-- ##### FUNCTION g_tree_insert ##### --> <!-- ##### FUNCTION g_tree_insert ##### -->
<para> <para>
Inserts a key/value pair into a #GTree. Inserts a key/value pair into a #GTree.

View File

@ -1,3 +1,82 @@
Mon Dec 11 04:44:11 2000 Tim Janik <timj@gtk.org>
* gboxed.c: fixed dealing with collection/lcopy of NULL values.
* gclosure.h: removed insane ramblings, added G_CALLBACK() a casting
convenience macro.
* Makefile.am: cleanups, marshaller generation rules.
* gmarshal.[hc]: new files with GRuntime standard marshallers.
* glib-genmarshal.c: fix log domain, support gruntime standard
marshallers, suport G_TYPE_PARAM, come with extern "C" and
#include gmarshal.h.
* glib-genmarshal.1: reflect glib-genmarshal.c updates.
* gobject.[hc]: implement object constructor. rework parameter
changed notification queueing, we support queue freezes now and
don't dispatch from an idle handler anymore.
parameter->property rename hassle.
implemented ::properties_changed and ::notify::* signals for
property change notification (the later supports property names
as details). added signal connection and named data properties.
(g_signal_connect_object): new function to setup while_alive
connections.
(g_object_class_install_property): sink properties now, since they
are initially floating.
(g_object_steal_data):
(g_object_set_data_full):
(g_object_set_data):
(g_object_get_data): set/get data by using g_datalist_*() functions
directly.
(g_object_queue_param_changed): nuked.
(g_object_freeze_notify): start queueing of property changes (freeze/
thaw calls stack).
(g_object_notify): announce changes of a certain property directly.
(g_object_thaw_notify): process queue of property changes, therefore
emitting GObject::notify::detail with detail being the changed
properties names.
(G_OBJECT_WARN_INVALID_PROPERTY_ID): saner macro variant of former
G_WARN_INVALID_PARAM_ID().
* gparam.[hc]: param specs are now initially floating and need to be
sunken with g_param_spec_sink(), support G_TYPE_PARAM values.
added G_PARAM_CONSTRUCT and G_PARAM_CONSTRUCT_ONLY parameter flags,
required by GObjectClass.constructor().
* gparamspecs.[hc]: added GParamSpecParam, GParamSpecPointer and
GParamSpecCCallback, param specs for G_TYPE_PARAM, G_TYPE_POINTER
and G_TYPE_CCALLBACK respectively.
* gsignal.[hc]: cleanups.
(signal_id_lookup): after walking the anchestry, try interfaces as well.
(g_signal_new): new function to create signals from varargs type list.
(g_signal_connect_closure): closure connection variant that works from
signal name+detail.
(g_signal_connect_data): c handler connection variant that works from
signal name+detail.
(g_signal_emit_valist): emit signal for an instance with paraneters
collected from a va_list.
(g_signal_emit): emit signal, taking parameters from varargs list.
(g_signal_emit_by_name): same as g_signal_emit, working from
signal name+detail.
(signal_emit_R): return whether return_value needs to be altered.
* gtype.[hc]: set log-domain to GRuntime, i'm slowly getting to all
the points that need to reflect the upcoming rename.
melt g_type_conforms_to() functionality into g_type_is_a(), as that
is what we really want (liskov substitution principle).
assorted changes to other files due to conforms_to->is_a.
* gvalue.[hc]: implemented g_value_set_instance() that sets a value
from an instantiatable type via the value_table's collect_value()
function (based on an idea from James Henstridge <james@daa.com.au>).
cleanups/fixes.
* gvaluetypes.[hc]: implement G_TYPE_CCALLBACK and G_TYPE_PARAM.
Wed Nov 29 13:30:05 2000 Tim Janik <timj@gtk.org> Wed Nov 29 13:30:05 2000 Tim Janik <timj@gtk.org>
* gsignal.c (handlers_find): fix elliots "logic fix" that dereferences * gsignal.c (handlers_find): fix elliots "logic fix" that dereferences

View File

@ -1,81 +1,144 @@
# GObject - GLib Type, Object, Parameter and Signal Library # GRuntime - GLib Type, Object, Parameter and Signal Library
# Copyright (C) 1997,98,99,2000 Tim Janik and Red Hat, Inc. # Copyright (C) 1997,98,99,2000 Tim Janik and Red Hat, Inc.
# #
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir) -I$(top_builddir) @GLIB_DEBUG_FLAGS@ INCLUDES = @STRIP_BEGIN@ \
-DG_LOG_DOMAIN=g_log_domain_gruntime \
-I$(top_srcdir) \
-I$(top_builddir) \
@GLIB_DEBUG_FLAGS@ \
@STRIP_END@
# libraries to compile and install # libraries to compile and install
lib_LTLIBRARIES = libgobject-1.3.la lib_LTLIBRARIES = libgobject-1.3.la
# provide g_logv() domain
AM_CFLAGS = -DG_LOG_DOMAIN=g_log_domain_gobject
# libtool stuff: set version and export symbols for resolving # libtool stuff: set version and export symbols for resolving
libgobjectincludedir = $(includedir)/glib-2.0/gobject libgobjectincludedir = $(includedir)/glib-2.0/gobject
libgobject_1_3_la_LDFLAGS = \ libgobject_1_3_la_LDFLAGS = @STRIP_BEGIN@ \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
-export-dynamic -export-dynamic \
@STRIP_END@
libgobject_1_3_la_LIBADD = # $(libglib) libgobject_1_3_la_LIBADD = # $(libglib)
# #
# setup source file variables # setup source file variables
# #
# GObject header files for public installation (non-generated) # GRuntime header files for public installation (non-generated)
gobject_public_h_sources = @STRIP_BEGIN@ \ gruntime_public_h_sources = @STRIP_BEGIN@ \
gboxed.h \ gboxed.h \
gbsearcharray.h \ gbsearcharray.h \
gclosure.h \ gclosure.h \
genums.h \ genums.h \
gobject.h \ gobject.h \
gparam.h \ gparam.h \
gparamspecs.h \ gparamspecs.h \
gsignal.h \ gsignal.h \
gtype.h \ gtype.h \
gtypemodule.h \ gtypemodule.h \
gtypeplugin.h \ gtypeplugin.h \
gvalue.h \ gvalue.h \
gvaluecollector.h \ gvaluecollector.h \
gvaluetypes.h \ gvaluetypes.h \
@STRIP_END@
# GRuntime header files that don't get installed
gruntime_private_h_sources =
# GRuntime C sources to build the library from
gruntime_c_sources = @STRIP_BEGIN@ \
gboxed.c \
gbsearcharray.c \
gclosure.c \
genums.c \
gobject.c \
gparam.c \
gparamspecs.c \
gsignal.c \
gtype.c \
gtypemodule.c \
gtypeplugin.c \
gvalue.c \
gvaluetypes.c \
@STRIP_END@ @STRIP_END@
# private GObject header files # we use our own built_sources variable rules to avoid automake's
gobject_private_h_sources = # BUILT_SOURCES oddities
# we generate frequently rebuild files piggyback on a stamp file, so sources
# depending on them only get rebuild when the built source actually changed
# content
# GObject C sources to build the library from # built sources that get installed with the header files
gobject_c_sources = @STRIP_BEGIN@ \ gruntime_built_public_sources = @STRIP_BEGIN@ \
gboxed.c \ gmarshal.h \
gbsearcharray.c \ @STRIP_END@
gclosure.c \ # built sources that don't get installed
genums.c \ gruntime_built_sources = @STRIP_BEGIN@ \
gobject.c \ stamp-gmarshal.h \
gparam.c \ gmarshal.c \
gparamspecs.c \ ${gruntime_built_public_sources} \
gsignal.c \
gtype.c \
gtypemodule.c \
gtypeplugin.c \
gvalue.c \
gvaluetypes.c \
@STRIP_END@ @STRIP_END@
# non-header sources (headers should be specified in the above variables) # 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 # that don't serve as direct make target sources, i.e. they don't have
# their own .lo rules and don't get publically installed # their own .lo rules and don't get publically installed
gobject_extra_sources = gruntime_extra_sources = @STRIP_BEGIN@ \
gmarshal.list \
gmarshal.strings \
@STRIP_END@
# #
# setup GObject sources and their dependancies # setup GRuntime sources and their dependancies
# #
gobject_h_sources = $(gobject_private_h_sources) $(gobject_public_h_sources) # $(gobject_built_public_sources) gruntime_target_headers = $(gruntime_public_h_sources) $(gruntime_built_public_sources)
libgobjectinclude_HEADERS = $(gobject_public_h_sources) # $(gobject_built_public_sources) gruntime_target_sources = $(gruntime_c_sources)
libgobject_1_3_la_SOURCES = $(gobject_c_sources) MAINTAINERCLEANFILES += $(gruntime_built_sources)
MAINTAINERCLEANFILES +=
# $(gobject_built_public_sources) $(gobject_built_sources)
EXTRA_HEADERS += EXTRA_HEADERS +=
EXTRA_DIST += $(gobject_private_h_sources) EXTRA_DIST += $(gruntime_private_h_sources) $(gruntime_extra_sources)
EXTRA_DIST += $(gobject_extra_sources) EXTRA_DIST += $(gruntime_built_sources)
# $(gobject_built_sources) $(gobject_built_public_sources)
#
# rules to generate built sources
#
# setup autogeneration dependancies
gen_sources = xgen-gmh xgen-gmc xgen-gms
CLEANFILES += $(gen_sources)
Makefile: oldest-source-stamp # oh boy, does automake SUCK!
oldest-source-stamp: $(gruntime_built_sources)
$(OBJECTS): oldest-source-stamp ${gruntime_built_public_sources} # this is our oldest file, used for implicit auto-generation deps
# initial creation of the real stamp-* files
gmarshal.h: # never add deps here
test -f "$(srcdir)/$@" || touch $(srcdir)/$@
# normal autogeneration rules
# all autogenerated files need to be generated in the srcdir,
# so old versions get remade and are not confused with newer
# versions in the build dir. thus a development setup requires
# srcdir to be writable, passing --disable-rebuilds to
# ../configure will supress all autogeneration rules.
$(srcdir)/stamp-gmarshal.h: @REBUILD@ gmarshal.list gmarshal.h glib-genmarshal
cd $(srcdir) \
&& echo "#ifndef __G_MARSHAL_H__" > xgen-gmh \
&& echo "#define __G_MARSHAL_H__" >> xgen-gmh \
&& ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal gmarshal.list --header >> xgen-gmh \
&& echo "#endif /* __G_MARSHAL_H__ */" >> xgen-gmh \
&& (cmp -s xgen-gmh gmarshal.h || cp xgen-gmh gmarshal.h) \
&& rm -f xgen-gmh xgen-gmh~ \
&& echo timestamp > $(@F)
$(srcdir)/gmarshal.c: @REBUILD@ $(srcdir)/stamp-gmarshal.h
cd $(srcdir) \
&& ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal gmarshal.list --body >> xgen-gmc \
&& cp xgen-gmc gmarshal.c \
&& rm -f xgen-gmc xgen-gmc~
$(srcdir)/gmarshal.strings: @REBUILD@ $(srcdir)/gmarshal.list
cd $(srcdir) \
&& grep '^[A-Z]' $(srcdir)/gmarshal.list \
| sed -e 's/^/"g_cclosure_marshal_/' -e 's/:/__/' -e 's/,/_/g' -e 's/$$/",/' > xgen-gms \
&& cp xgen-gms gmarshal.strings \
&& rm -f xgen-gms xgen-gms~
glib-genmarshal.o: gmarshal.strings
# target platform:
libgobjectinclude_HEADERS = $(gruntime_target_headers)
libgobject_1_3_la_SOURCES = $(gruntime_target_sources)
# #
# programs to compile and install # programs to compile and install
@ -86,8 +149,8 @@ gobject_query_SOURCES = gobject-query.c
glib_genmarshal_SOURCES = glib-genmarshal.c glib_genmarshal_SOURCES = glib-genmarshal.c
# link programs against libgobject # link programs against libgobject
progs_LDADD = ../libglib-1.3.la libgobject-1.3.la progs_LDADD = ../libglib-1.3.la libgobject-1.3.la
glib_genmarshal_LDADD = ../libglib-1.3.la # can't have libgobject here
gobject_query_LDADD = $(progs_LDADD) gobject_query_LDADD = $(progs_LDADD)
glib_genmarshal_LDADD = $(progs_LDADD)
# #
# manual pages to install # manual pages to install
@ -123,4 +186,3 @@ dist-hook: $(BUILT_EXTRA_DIST)
for f in $$files; do \ for f in $$files; do \
if test -f $$f; then d=.; else d=$(srcdir); fi; \ if test -f $$f; then d=.; else d=$(srcdir); fi; \
cp $$d/$$f $(distdir) || exit 1; done cp $$d/$$f $(distdir) || exit 1; done

View File

@ -127,7 +127,7 @@ boxed_proxy_collect_value (GValue *value,
key.type = value->g_type; key.type = value->g_type;
node = g_bsearch_array_lookup (&boxed_bsa, &key); node = g_bsearch_array_lookup (&boxed_bsa, &key);
value->data[0].v_pointer = node->copy (collect_value->v_pointer); value->data[0].v_pointer = collect_value->v_pointer ? node->copy (collect_value->v_pointer) : NULL;
*collect_type = 0; *collect_type = 0;
return NULL; return NULL;
@ -147,7 +147,7 @@ boxed_proxy_lcopy_value (const GValue *value,
key.type = value->g_type; key.type = value->g_type;
node = g_bsearch_array_lookup (&boxed_bsa, &key); node = g_bsearch_array_lookup (&boxed_bsa, &key);
*boxed_p = node->copy (value->data[0].v_pointer); *boxed_p = value->data[0].v_pointer ? node->copy (value->data[0].v_pointer) : NULL;
*collect_type = 0; *collect_type = 0;
return NULL; return NULL;

View File

@ -524,8 +524,8 @@ g_type_iface_meta_marshal (GClosure *closure,
} }
GClosure* GClosure*
g_signal_type_closure_new (GType itype, g_signal_type_cclosure_new (GType itype,
guint struct_offset) guint struct_offset)
{ {
GClosure *closure; GClosure *closure;

View File

@ -32,6 +32,7 @@ extern "C" {
/* --- defines --- */ /* --- defines --- */
#define G_CLOSURE_NEEDS_MARSHAL(closure) (((GClosure*) (closure))->marshal == NULL) #define G_CLOSURE_NEEDS_MARSHAL(closure) (((GClosure*) (closure))->marshal == NULL)
#define G_CCLOSURE_SWAP_DATA(cclosure) (((GClosure*) (closure))->derivative_flag) #define G_CCLOSURE_SWAP_DATA(cclosure) (((GClosure*) (closure))->derivative_flag)
#define G_CALLBACK(f) ((GCallback) (f))
/* -- typedefs --- */ /* -- typedefs --- */
@ -105,7 +106,7 @@ GClosure* g_cclosure_new (GCallback callback_func,
GClosure* g_cclosure_new_swap (GCallback callback_func, GClosure* g_cclosure_new_swap (GCallback callback_func,
gpointer user_data, gpointer user_data,
GClosureNotify destroy_data); GClosureNotify destroy_data);
GClosure* g_signal_type_closure_new (GType itype, GClosure* g_signal_type_cclosure_new (GType itype,
guint struct_offset); guint struct_offset);
@ -146,35 +147,14 @@ void g_closure_invoke (GClosure *closure,
/* FIXME: /* FIXME:
data_object::destroy -> closure_invalidate(); OK: data_object::destroy -> closure_invalidate();
closure_invalidate() -> disconnect(closure); MIS: closure_invalidate() -> disconnect(closure);
disconnect(closure) -> (unlink) closure_unref(); MIS: disconnect(closure) -> (unlink) closure_unref();
closure_finalize() -> g_free (data_string); OK: closure_finalize() -> g_free (data_string);
1) need GObject and GType in glib random remarks:
2) need GParam - need marshaller repo with decent aliasing to base types
3) need to resolve dtor cycles - provide marshaller collection, virtually covering anything out there
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
*/ */

View File

@ -35,6 +35,10 @@ Specify marshaller prefix. The default prefix is `\fIg_cclosure_marshal\fP'.
\fI--skip-source \fI--skip-source
Skip source location remarks in generated comments. Skip source location remarks in generated comments.
.TP .TP
\fI--nostdinc
Do not use the standard GRuntime marshallers, and skip gmarshal.h include
directive in generated header files.
.TP
\fI--g-fatal-warnings \fI--g-fatal-warnings
Make warnings fatal, that is, exit immediately once a warning occours. Make warnings fatal, that is, exit immediately once a warning occours.
.TP .TP
@ -118,6 +122,8 @@ for string types (gchar*)
\fIBOXED \fIBOXED
for boxed (anonymous but reference counted) types (GBoxed*) for boxed (anonymous but reference counted) types (GBoxed*)
.TP 12 .TP 12
\fIPARAM
for GParamSpec or derived types (GParamSpec*)
\fIPOINTER \fIPOINTER
for anonymous pointer types (gpointer) for anonymous pointer types (gpointer)
.TP 12 .TP 12

View File

@ -18,7 +18,13 @@
*/ */
#include "config.h" #include "config.h"
#include <glib-object.h>
/* ok, this is a bit hackish, have to provide gruntime log domain as
* we don't link against -lgruntime
*/
char *g_log_domain_gruntime = "GLib-Genmarshal";
#include <glib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -108,11 +114,13 @@ static GScannerConfig scanner_config_template =
FALSE /* symbol_2_token */, FALSE /* symbol_2_token */,
FALSE /* scope_0_fallback */, FALSE /* scope_0_fallback */,
}; };
static gchar *marshaller_prefix = "g_cclosure_marshal"; static gchar *std_marshaller_prefix = "g_cclosure_marshal";
static gchar *marshaller_prefix = "g_cclosure_user_marshal";
static GHashTable *marshallers = NULL; static GHashTable *marshallers = NULL;
static gboolean gen_cheader = FALSE; static gboolean gen_cheader = FALSE;
static gboolean gen_cbody = FALSE; static gboolean gen_cbody = FALSE;
static gboolean skip_ploc = FALSE; static gboolean skip_ploc = FALSE;
static gboolean std_includes = TRUE;
/* --- functions --- */ /* --- functions --- */
@ -142,12 +150,14 @@ complete_arg (Argument *arg,
{ "STRING", "POINTER", "as_pointer", "gpointer", }, { "STRING", "POINTER", "as_pointer", "gpointer", },
{ "BOXED", "POINTER", "as_pointer", "gpointer", }, { "BOXED", "POINTER", "as_pointer", "gpointer", },
{ "POINTER", "POINTER", "as_pointer", "gpointer", }, { "POINTER", "POINTER", "as_pointer", "gpointer", },
{ "PARAM", "POINTER", "as_pointer", "gpointer", },
{ "OBJECT", "POINTER", "as_pointer", "gpointer", }, { "OBJECT", "POINTER", "as_pointer", "gpointer", },
}; };
static const Argument out_arguments[] = { static const Argument out_arguments[] = {
{ "STRING", "STRING", "string", "gchar*", }, { "STRING", "STRING", "string", "gchar*", },
{ "BOXED", "BOXED", "boxed", "gpointer", }, { "BOXED", "BOXED", "boxed", "gpointer", },
{ "POINTER", "POINTER", "pointer", "gpointer", }, { "POINTER", "POINTER", "pointer", "gpointer", },
{ "PARAM", "PARAM", "param", "GParamSpec*", },
{ "OBJECT", "OBJECT", "object", "GObject*", }, { "OBJECT", "OBJECT", "object", "GObject*", },
}; };
const guint n_inout_arguments = sizeof (inout_arguments) / sizeof (inout_arguments[0]); const guint n_inout_arguments = sizeof (inout_arguments) / sizeof (inout_arguments[0]);
@ -201,7 +211,7 @@ pad (const gchar *string)
{ {
g_free (buffer); g_free (buffer);
buffer = g_strdup_printf ("%s ", string); buffer = g_strdup_printf ("%s ", string);
g_warning ("overfull string (%lu bytes) for padspace", strlen (string)); g_warning ("overfull string (%u bytes) for padspace", (guint) strlen (string));
return buffer; return buffer;
} }
@ -241,17 +251,39 @@ generate_marshal (const gchar *signame,
{ {
guint ind, a; guint ind, a;
GList *node; GList *node;
gchar *tmp = g_strconcat (marshaller_prefix, "_", signame, NULL);
gboolean have_std_marshaller = FALSE;
if (g_hash_table_lookup (marshallers, signame)) /* here we have to make sure a marshaller named <marshaller_prefix>_<signame>
return; * exists. we might have put it out already, can revert to a standard marshaller
* provided by glib, or need to generate one.
*/
if (g_hash_table_lookup (marshallers, tmp))
{
/* done, marshaller already generated */
g_free (tmp);
return;
}
else else
{ {
gchar *tmp = g_strdup (signame); /* need to alias/generate marshaller, register name */
g_hash_table_insert (marshallers, tmp, tmp); g_hash_table_insert (marshallers, tmp, tmp);
} }
if (gen_cheader) /* can we revert to a standard marshaller? */
if (std_includes)
{
tmp = g_strconcat (std_marshaller_prefix, "_", signame, NULL);
have_std_marshaller = g_hash_table_lookup (marshallers, tmp) != NULL;
g_free (tmp);
}
if (gen_cheader && have_std_marshaller)
{
fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, signame, std_marshaller_prefix, signame);
}
if (gen_cheader && !have_std_marshaller)
{ {
ind = fprintf (fout, "extern void "); ind = fprintf (fout, "extern void ");
ind += fprintf (fout, "%s_%s (", marshaller_prefix, signame); ind += fprintf (fout, "%s_%s (", marshaller_prefix, signame);
@ -262,7 +294,7 @@ generate_marshal (const gchar *signame,
fprintf (fout, "%sgpointer invocation_hint,\n", indent (ind)); fprintf (fout, "%sgpointer invocation_hint,\n", indent (ind));
fprintf (fout, "%sgpointer marshal_data);\n", indent (ind)); fprintf (fout, "%sgpointer marshal_data);\n", indent (ind));
} }
if (gen_cbody) if (gen_cbody && !have_std_marshaller)
{ {
/* cfile marhsal header */ /* cfile marhsal header */
fprintf (fout, "void\n"); fprintf (fout, "void\n");
@ -352,7 +384,7 @@ generate_marshal (const gchar *signame,
static void static void
process_signature (Signature *sig) process_signature (Signature *sig)
{ {
gchar *pname, *sname; gchar *pname, *sname, *tmp;
GList *node; GList *node;
/* lookup and complete info on arguments */ /* lookup and complete info on arguments */
@ -400,18 +432,19 @@ process_signature (Signature *sig)
fprintf (fout, " (%s)", sig->ploc); fprintf (fout, " (%s)", sig->ploc);
fprintf (fout, " */\n"); fprintf (fout, " */\n");
/* generate signature marshaller */ /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
generate_marshal (sname, sig); generate_marshal (sname, sig);
/* put out marshaler alias if required */ /* put out marshaller alias for requested name if required (<marshaller_prefix>_<pname>) */
if (gen_cheader && !g_hash_table_lookup (marshallers, pname)) tmp = g_strconcat (marshaller_prefix, "_", pname, NULL);
if (gen_cheader && !g_hash_table_lookup (marshallers, tmp))
{ {
gchar *tmp = g_strdup (pname);
fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, pname, marshaller_prefix, sname); fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, pname, marshaller_prefix, sname);
g_hash_table_insert (marshallers, tmp, tmp); g_hash_table_insert (marshallers, tmp, tmp);
} }
else
g_free (tmp);
g_free (pname); g_free (pname);
g_free (sname); g_free (sname);
@ -482,6 +515,9 @@ int
main (int argc, main (int argc,
char *argv[]) char *argv[])
{ {
const gchar *gruntime_marshallers[] = {
#include "gmarshal.strings"
};
GScanner *scanner; GScanner *scanner;
GSList *slist, *files = NULL; GSList *slist, *files = NULL;
gint i; gint i;
@ -502,6 +538,24 @@ main (int argc,
fout = stdout; fout = stdout;
marshallers = g_hash_table_new (g_str_hash, g_str_equal); marshallers = g_hash_table_new (g_str_hash, g_str_equal);
/* add GRuntime standard marshallers */
if (std_includes)
for (i = 0; i < sizeof (gruntime_marshallers) / sizeof (gruntime_marshallers[0]); i++)
{
gchar *tmp = g_strdup (gruntime_marshallers[i]);
g_hash_table_insert (marshallers, tmp, tmp);
}
/* put out initial heading */
fprintf (fout, "\n");
if (gen_cheader)
{
if (std_includes)
fprintf (fout, "#include\t<gobject/gmarshal.h>\n\n");
fprintf (fout, "#ifdef __cplusplus\nextern \"C\" {\n#endif /* __cplusplus */\n");
}
/* process input files */ /* process input files */
for (slist = files; slist; slist = slist->next) for (slist = files; slist; slist = slist->next)
{ {
@ -579,6 +633,13 @@ main (int argc,
close (fd); close (fd);
} }
/* put out trailer */
if (gen_cheader)
{
fprintf (fout, "\n#ifdef __cplusplus\n}\n#endif /* __cplusplus */\n");
}
fprintf (fout, "\n");
/* clean up */ /* clean up */
g_slist_free (files); g_slist_free (files);
g_scanner_destroy (scanner); g_scanner_destroy (scanner);
@ -613,6 +674,16 @@ parse_args (gint *argc_p,
skip_ploc = TRUE; skip_ploc = TRUE;
argv[i] = NULL; argv[i] = NULL;
} }
else if (strcmp ("--nostdinc", argv[i]) == 0)
{
std_includes = FALSE;
argv[i] = NULL;
}
else if (strcmp ("--stdinc", argv[i]) == 0)
{
std_includes = TRUE;
argv[i] = NULL;
}
else if ((strcmp ("--prefix", argv[i]) == 0) || else if ((strcmp ("--prefix", argv[i]) == 0) ||
(strncmp ("--prefix=", argv[i], 9) == 0)) (strncmp ("--prefix=", argv[i], 9) == 0))
{ {
@ -690,12 +761,13 @@ print_blurb (FILE *bout,
else else
{ {
fprintf (bout, "Usage: %s [options] [files...]\n", PRG_NAME); fprintf (bout, "Usage: %s [options] [files...]\n", PRG_NAME);
fprintf (bout, " --header generate C headers\n"); fprintf (bout, " --header generate C headers\n");
fprintf (bout, " --body generate C code\n"); fprintf (bout, " --body generate C code\n");
fprintf (bout, " --prefix=string specify marshaller prefix\n"); fprintf (bout, " --prefix=string specify marshaller prefix\n");
fprintf (bout, " --skip-source skip source location comments\n"); fprintf (bout, " --skip-source skip source location comments\n");
fprintf (bout, " -h, --help show this help message\n"); fprintf (bout, " --stdinc, --nostdinc include/use GRuntime standard marshallers\n");
fprintf (bout, " -v, --version print version informations\n"); fprintf (bout, " -h, --help show this help message\n");
fprintf (bout, " --g-fatal-warnings make warnings fatal (abort)\n"); fprintf (bout, " -v, --version print version informations\n");
fprintf (bout, " --g-fatal-warnings make warnings fatal (abort)\n");
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * 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. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General * You should have received a copy of the GNU Lesser General
@ -19,10 +19,10 @@
#ifndef __G_OBJECT_H__ #ifndef __G_OBJECT_H__
#define __G_OBJECT_H__ #define __G_OBJECT_H__
#include <gobject/gtype.h> #include <gobject/gtype.h>
#include <gobject/gvalue.h> #include <gobject/gvalue.h>
#include <gobject/gparam.h> #include <gobject/gparam.h>
#include <gobject/gclosure.h> #include <gobject/gclosure.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -31,161 +31,177 @@ extern "C" {
/* --- type macros --- */ /* --- type macros --- */
#define G_TYPE_IS_OBJECT(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT) #define G_TYPE_IS_OBJECT(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT)
#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject)) #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_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(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_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_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(object) (G_TYPE_FROM_INSTANCE (object))
#define G_OBJECT_TYPE_NAME(object) (g_type_name (G_OBJECT_TYPE (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_TYPE(class) (G_TYPE_FROM_CLASS (class))
#define G_OBJECT_CLASS_NAME(class) (g_type_name (G_OBJECT_CLASS_TYPE (class))) #define G_OBJECT_CLASS_NAME(class) (g_type_name (G_OBJECT_CLASS_TYPE (class)))
#define G_IS_VALUE_OBJECT(value) (G_TYPE_CHECK_VALUE_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 --- */ /* --- typedefs & structures --- */
typedef struct _GObject GObject; typedef struct _GObject GObject;
typedef struct _GObjectClass GObjectClass; typedef struct _GObjectClass GObjectClass;
typedef struct _GObjectConstructParam GObjectConstructParam; typedef struct _GObjectConstructParam GObjectConstructParam;
typedef void (*GObjectGetParamFunc) (GObject *object, typedef void (*GObjectGetPropertyFunc) (GObject *object,
guint param_id, guint property_id,
GValue *value, GValue *value,
GParamSpec *pspec, GParamSpec *pspec,
const gchar *trailer); const gchar *trailer);
typedef void (*GObjectSetParamFunc) (GObject *object, typedef void (*GObjectSetPropertyFunc) (GObject *object,
guint param_id, guint property_id,
const GValue *value, const GValue *value,
GParamSpec *pspec, GParamSpec *pspec,
const gchar *trailer); const gchar *trailer);
typedef void (*GObjectFinalizeFunc) (GObject *object); typedef void (*GObjectFinalizeFunc) (GObject *object);
struct _GObject struct _GObject
{ {
GTypeInstance g_type_instance; GTypeInstance g_type_instance;
/*< private >*/ /*< private >*/
guint ref_count; guint ref_count;
GData *qdata; GData *qdata;
}; };
struct _GObjectClass struct _GObjectClass
{ {
GTypeClass g_type_class; GTypeClass g_type_class;
guint n_param_specs; /* private, these fields might vanish */
GParamSpec **param_specs; guint n_property_specs;
GParamSpec **property_specs;
GObject* (*constructor) (GType type, // FIXME!!! /* public overridable methods */
guint n_construct_params, GObject* (*constructor) (GType type,
GObjectConstructParam *construct_params); guint n_construct_properties,
void (*get_param) (GObject *object, GObjectConstructParam *construct_params);
guint param_id, void (*get_property) (GObject *object,
GValue *value, guint property_id,
GParamSpec *pspec, GValue *value,
const gchar *trailer); GParamSpec *pspec,
void (*set_param) (GObject *object, const gchar *trailer);
guint param_id, void (*set_property) (GObject *object,
const GValue *value, guint property_id,
GParamSpec *pspec, const GValue *value,
const gchar *trailer); GParamSpec *pspec,
void (*queue_param_changed) (GObject *object, const gchar *trailer);
void (*shutdown) (GObject *object);
void (*finalize) (GObject *object);
/*< private >*/
void (*dispatch_properties_changed) (GObject *object,
guint n_pspecs,
GParamSpec **pspecs);
/* signals */
void (*properties_changed) (GObject *object,
guint n_pspecs,
GParamSpec **pspecs);
void (*notify) (GObject *object,
GParamSpec *pspec); GParamSpec *pspec);
void (*dispatch_param_changed) (GObject *object,
GParamSpec *pspec);
void (*shutdown) (GObject *object);
void (*finalize) (GObject *object);
}; };
struct _GObjectConstructParam struct _GObjectConstructParam
{ {
GParamSpec *pspec; GParamSpec *pspec;
GValue *value; GValue *value;
gchar *trailer; const gchar *trailer;
}; };
/* --- prototypes --- */ /* --- prototypes --- */
void g_object_class_install_param (GObjectClass *oclass, void g_object_class_install_property (GObjectClass *oclass,
guint param_id, guint property_id,
GParamSpec *pspec /* +1 ref */); GParamSpec *pspec);
GParamSpec* g_object_class_find_param_spec (GObjectClass *oclass, GParamSpec* g_object_class_find_property (GObjectClass *oclass,
const gchar *param_name); const gchar *property_name);
gpointer g_object_new (GType object_type, gpointer g_object_new (GType object_type,
const gchar *first_param_name, const gchar *first_property_name,
...); ...);
gpointer g_object_new_valist (GType object_type, gpointer g_object_new_valist (GType object_type,
const gchar *first_param_name, const gchar *first_property_name,
va_list var_args); va_list var_args);
void g_object_set (GObject *object, void g_object_set (GObject *object,
const gchar *first_param_name, const gchar *first_property_name,
...); ...);
void g_object_get (GObject *object, void g_object_get (GObject *object,
const gchar *first_param_name, const gchar *first_property_name,
...); ...);
void g_object_set_valist (GObject *object, void g_object_set_valist (GObject *object,
const gchar *first_param_name, const gchar *first_property_name,
va_list var_args); va_list var_args);
void g_object_get_valist (GObject *object, void g_object_get_valist (GObject *object,
const gchar *first_param_name, const gchar *first_property_name,
va_list var_args); va_list var_args);
void g_object_set_param (GObject *object, void g_object_set_property (GObject *object,
const gchar *param_name, const gchar *property_name,
const GValue *value); const GValue *value);
void g_object_get_param (GObject *object, void g_object_get_property (GObject *object,
const gchar *param_name, const gchar *property_name,
GValue *value); GValue *value);
void g_object_queue_param_changed (GObject *object, void g_object_freeze_notify (GObject *object);
const gchar *param_name); void g_object_notify (GObject *object,
GObject* g_object_ref (GObject *object); const gchar *property_name);
void g_object_unref (GObject *object); void g_object_thaw_notify (GObject *object);
gpointer g_object_get_qdata (GObject *object, GObject* g_object_ref (GObject *object);
GQuark quark); void g_object_unref (GObject *object);
void g_object_set_qdata (GObject *object, gpointer g_object_get_qdata (GObject *object,
GQuark quark, GQuark quark);
gpointer data); void g_object_set_qdata (GObject *object,
void g_object_set_qdata_full (GObject *object, GQuark quark,
GQuark quark, gpointer data);
gpointer data, void g_object_set_qdata_full (GObject *object,
GDestroyNotify destroy); GQuark quark,
gpointer g_object_steal_qdata (GObject *object, gpointer data,
GQuark quark); GDestroyNotify destroy);
gpointer g_object_get_data (GObject *object, gpointer g_object_steal_qdata (GObject *object,
const gchar *key); GQuark quark);
void g_object_set_data (GObject *object, gpointer g_object_get_data (GObject *object,
const gchar *key, const gchar *key);
gpointer data); void g_object_set_data (GObject *object,
void g_object_set_data_full (GObject *object, const gchar *key,
const gchar *key, gpointer data);
gpointer data, void g_object_set_data_full (GObject *object,
GDestroyNotify destroy); const gchar *key,
gpointer g_object_steal_data (GObject *object, gpointer data,
const gchar *key); GDestroyNotify destroy);
void g_object_watch_closure (GObject *object, gpointer g_object_steal_data (GObject *object,
GClosure *closure); const gchar *key);
GClosure* g_cclosure_new_object (GCallback callback_func, void g_object_watch_closure (GObject *object,
gpointer object); GClosure *closure);
GClosure* g_cclosure_new_object_swap (GCallback callback_func, GClosure* g_cclosure_new_object (GCallback callback_func,
gpointer object); gpointer object);
GClosure* g_closure_new_object (guint sizeof_closure, GClosure* g_cclosure_new_object_swap (GCallback callback_func,
GObject *object); gpointer object);
void g_value_set_object (GValue *value, GClosure* g_closure_new_object (guint sizeof_closure,
GObject *v_object); GObject *object);
GObject* g_value_get_object (const GValue *value); void g_value_set_object (GValue *value,
GObject* g_value_dup_object (const GValue *value); GObject *v_object);
GObject* g_value_get_object (const GValue *value);
GObject* g_value_dup_object (const GValue *value);
guint g_signal_connect_object (gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer gobject,
gboolean swapped,
gboolean after);
/* --- implementation macros --- */ /* --- implementation macros --- */
#define G_WARN_INVALID_PARAM_ID(object, param_id, pspec) \ #define G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec) \
G_STMT_START { \ G_STMT_START { \
GObject *_object = (GObject*) (object); \ GObject *_object = (GObject*) (object); \
GParamSpec *_pspec = (GParamSpec*) (pspec); \ GParamSpec *_pspec = (GParamSpec*) (pspec); \
guint _param_id = (param_id); \ guint _property_id = (property_id); \
g_warning ("%s: invalid parameter id %u for \"%s\" of type `%s' in `%s'", \ g_warning ("%s: invalid property id %u for \"%s\" of type `%s' in `%s'", \
G_STRLOC, \ G_STRLOC, \
_param_id, \ _property_id, \
_pspec->name, \ _pspec->name, \
g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \ g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \
G_OBJECT_TYPE_NAME (_object)); \ G_OBJECT_TYPE_NAME (_object)); \
} G_STMT_END } G_STMT_END

View File

@ -19,12 +19,14 @@
#include "gparam.h" #include "gparam.h"
#include "gvaluecollector.h"
#include <string.h> #include <string.h>
/* --- defines --- */ /* --- defines --- */
#define G_PARAM_SPEC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass)) #define G_PARAM_SPEC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
#define PSPEC_APPLIES_TO_VALUE(pspec, value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
/* --- prototypes --- */ /* --- prototypes --- */
@ -34,6 +36,23 @@ static void g_param_spec_class_init (GParamSpecClass *class,
gpointer class_data); gpointer class_data);
static void g_param_spec_init (GParamSpec *pspec); static void g_param_spec_init (GParamSpec *pspec);
static void g_param_spec_finalize (GParamSpec *pspec); static void g_param_spec_finalize (GParamSpec *pspec);
static void value_param_init (GValue *value);
static void value_param_free_value (GValue *value);
static void value_param_copy_value (const GValue *src_value,
GValue *dest_value);
static gpointer value_param_peek_pointer (const GValue *value);
static gchar* value_param_collect_value (GValue *value,
guint nth_value,
GType *collect_type,
GTypeCValue *collect_value);
static gchar* value_param_lcopy_value (const GValue *value,
guint nth_value,
GType *collect_type,
GTypeCValue *collect_value);
/* --- variables --- */
static GQuark quark_floating = 0;
/* --- functions --- */ /* --- functions --- */
@ -46,6 +65,16 @@ g_param_type_init (void) /* sync with gtype.c */
G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DERIVABLE |
G_TYPE_FLAG_DEEP_DERIVABLE), G_TYPE_FLAG_DEEP_DERIVABLE),
}; };
static const GTypeValueTable param_value_table = {
value_param_init, /* value_init */
value_param_free_value, /* value_free */
value_param_copy_value, /* value_copy */
value_param_peek_pointer, /* value_peek_pointer */
G_VALUE_COLLECT_POINTER, /* collect_type */
value_param_collect_value, /* collect_value */
G_VALUE_COLLECT_POINTER, /* lcopy_type */
value_param_lcopy_value, /* lcopy_value */
};
static const GTypeInfo param_spec_info = { static const GTypeInfo param_spec_info = {
sizeof (GParamSpecClass), sizeof (GParamSpecClass),
@ -59,7 +88,7 @@ g_param_type_init (void) /* sync with gtype.c */
0, /* n_preallocs */ 0, /* n_preallocs */
(GInstanceInitFunc) g_param_spec_init, (GInstanceInitFunc) g_param_spec_init,
NULL, /* value_table */ &param_value_table,
}; };
GType type; GType type;
@ -81,6 +110,8 @@ static void
g_param_spec_class_init (GParamSpecClass *class, g_param_spec_class_init (GParamSpecClass *class,
gpointer class_data) gpointer class_data)
{ {
quark_floating = g_quark_from_static_string ("GParamSpec-floating");
class->value_type = G_TYPE_NONE; class->value_type = G_TYPE_NONE;
class->finalize = g_param_spec_finalize; class->finalize = g_param_spec_finalize;
class->value_set_default = NULL; class->value_set_default = NULL;
@ -98,6 +129,7 @@ g_param_spec_init (GParamSpec *pspec)
pspec->owner_type = 0; pspec->owner_type = 0;
pspec->qdata = NULL; pspec->qdata = NULL;
pspec->ref_count = 1; pspec->ref_count = 1;
g_datalist_id_set_data (&pspec->qdata, quark_floating, GUINT_TO_POINTER (TRUE));
} }
static void static void
@ -129,11 +161,28 @@ g_param_spec_unref (GParamSpec *pspec)
g_return_if_fail (G_IS_PARAM_SPEC (pspec)); g_return_if_fail (G_IS_PARAM_SPEC (pspec));
g_return_if_fail (pspec->ref_count > 0); g_return_if_fail (pspec->ref_count > 0);
/* sync with _sink */
pspec->ref_count -= 1; pspec->ref_count -= 1;
if (pspec->ref_count == 0) if (pspec->ref_count == 0)
G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec); G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
} }
void
g_param_spec_sink (GParamSpec *pspec)
{
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
g_return_if_fail (pspec->ref_count > 0);
if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
{
/* sync with _unref */
if (pspec->ref_count > 1)
pspec->ref_count -= 1;
else
g_param_spec_unref (pspec);
}
}
gpointer gpointer
g_param_spec_internal (GType param_type, g_param_spec_internal (GType param_type,
const gchar *name, const gchar *name,
@ -204,7 +253,7 @@ g_param_value_set_default (GParamSpec *pspec,
{ {
g_return_if_fail (G_IS_PARAM_SPEC (pspec)); g_return_if_fail (G_IS_PARAM_SPEC (pspec));
g_return_if_fail (G_IS_VALUE (value)); g_return_if_fail (G_IS_VALUE (value));
g_return_if_fail (G_IS_PARAM_VALUE (pspec, value)); g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
g_value_reset (value); g_value_reset (value);
G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value); G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);
@ -219,7 +268,7 @@ g_param_value_defaults (GParamSpec *pspec,
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
g_return_val_if_fail (G_IS_VALUE (value), FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE);
g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value), FALSE); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value); G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
@ -235,7 +284,7 @@ g_param_value_validate (GParamSpec *pspec,
{ {
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
g_return_val_if_fail (G_IS_VALUE (value), FALSE); g_return_val_if_fail (G_IS_VALUE (value), FALSE);
g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value), FALSE); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate) if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
{ {
@ -265,14 +314,90 @@ g_param_values_cmp (GParamSpec *pspec,
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0); g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
g_return_val_if_fail (G_IS_VALUE (value1), 0); g_return_val_if_fail (G_IS_VALUE (value1), 0);
g_return_val_if_fail (G_IS_VALUE (value2), 0); g_return_val_if_fail (G_IS_VALUE (value2), 0);
g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value1), 0); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value2), 0); g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2); cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
return CLAMP (cmp, -1, 1); return CLAMP (cmp, -1, 1);
} }
static void
value_param_init (GValue *value)
{
value->data[0].v_pointer = NULL;
}
static void
value_param_free_value (GValue *value)
{
if (value->data[0].v_pointer)
g_param_spec_unref (value->data[0].v_pointer);
}
static void
value_param_copy_value (const GValue *src_value,
GValue *dest_value)
{
dest_value->data[0].v_pointer = (src_value->data[0].v_pointer
? g_param_spec_ref (src_value->data[0].v_pointer)
: NULL);
}
static gpointer
value_param_peek_pointer (const GValue *value)
{
return value->data[0].v_pointer;
}
static gchar*
value_param_collect_value (GValue *value,
guint nth_value,
GType *collect_type,
GTypeCValue *collect_value)
{
if (collect_value->v_pointer)
{
GParamSpec *param = collect_value->v_pointer;
if (param->g_type_instance.g_class == NULL)
return g_strconcat ("invalid unclassed param spec pointer for value type `",
G_VALUE_TYPE_NAME (value),
"'",
NULL);
else if (!g_type_is_a (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
return g_strconcat ("invalid param spec type `",
G_PARAM_SPEC_TYPE_NAME (param),
"' for value type `",
G_VALUE_TYPE_NAME (value),
"'",
NULL);
value->data[0].v_pointer = g_param_spec_ref (param);
}
else
value->data[0].v_pointer = NULL;
*collect_type = 0;
return NULL;
}
static gchar*
value_param_lcopy_value (const GValue *value,
guint nth_value,
GType *collect_type,
GTypeCValue *collect_value)
{
GParamSpec **param_p = collect_value->v_pointer;
if (!param_p)
return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
*param_p = value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
*collect_type = 0;
return NULL;
}
static guint static guint
param_spec_hash (gconstpointer key_spec) param_spec_hash (gconstpointer key_spec)
{ {
@ -468,3 +593,34 @@ g_param_type_register_static (const gchar *name,
return g_type_register_static (G_TYPE_PARAM, name, &info, 0); return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
} }
void
g_value_set_param (GValue *value,
GParamSpec *param)
{
g_return_if_fail (G_IS_VALUE_PARAM (value));
if (param)
g_return_if_fail (G_IS_PARAM_SPEC (param));
if (value->data[0].v_pointer)
g_param_spec_unref (value->data[0].v_pointer);
value->data[0].v_pointer = param;
if (value->data[0].v_pointer)
g_param_spec_ref (value->data[0].v_pointer);
}
GParamSpec*
g_value_get_param (const GValue *value)
{
g_return_val_if_fail (G_IS_VALUE_PARAM (value), NULL);
return value->data[0].v_pointer;
}
GParamSpec*
g_value_dup_param (const GValue *value)
{
g_return_val_if_fail (G_IS_VALUE_PARAM (value), NULL);
return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
}

View File

@ -37,8 +37,8 @@ extern "C" {
#define G_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM, GParamSpec)) #define G_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM, GParamSpec))
#define G_IS_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM)) #define G_IS_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM))
#define G_PARAM_SPEC_GET_CLASS(pspec) (G_TYPE_INSTANCE_GET_CLASS ((pspec), G_TYPE_PARAM, GParamSpecClass)) #define G_PARAM_SPEC_GET_CLASS(pspec) (G_TYPE_INSTANCE_GET_CLASS ((pspec), G_TYPE_PARAM, GParamSpecClass))
#define G_IS_PARAM_VALUE(pspec, value) (g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec))) /* FIXME */
#define G_PARAM_SPEC_VALUE_TYPE(pspec) (G_PARAM_SPEC_GET_CLASS (pspec)->value_type) #define G_PARAM_SPEC_VALUE_TYPE(pspec) (G_PARAM_SPEC_GET_CLASS (pspec)->value_type)
#define G_IS_VALUE_PARAM(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_PARAM))
/* --- flags --- */ /* --- flags --- */
@ -46,15 +46,31 @@ typedef enum
{ {
G_PARAM_READABLE = 1 << 0, G_PARAM_READABLE = 1 << 0,
G_PARAM_WRITABLE = 1 << 1, G_PARAM_WRITABLE = 1 << 1,
G_PARAM_MASK = 0x000f, G_PARAM_CONSTRUCT = 1 << 2,
G_PARAM_CONSTRUCT_ONLY = 1 << 3,
#define G_PARAM_MASK (0x000f)
/* bits in the range 0xfff0 are reserved for 3rd party usage */ /* bits in the range 0xfff0 are reserved for 3rd party usage */
G_PARAM_USER_MASK = 0xfff0 #define G_PARAM_USER_MASK (0xfff0)
} GParamFlags; } GParamFlags;
/* --- typedefs & structures --- */ /* --- typedefs & structures --- */
typedef struct _GParamSpecClass GParamSpecClass;
typedef struct _GParamSpec GParamSpec; typedef struct _GParamSpec GParamSpec;
typedef struct _GParamSpecClass GParamSpecClass;
struct _GParamSpec
{
GTypeInstance g_type_instance;
gchar *name;
gchar *nick;
gchar *blurb;
GParamFlags flags;
/*< private >*/
GType owner_type;
GData *qdata;
guint ref_count;
};
struct _GParamSpecClass struct _GParamSpecClass
{ {
GTypeClass g_type_class; GTypeClass g_type_class;
@ -72,25 +88,12 @@ struct _GParamSpecClass
const GValue *value1, const GValue *value1,
const GValue *value2); const GValue *value2);
}; };
struct _GParamSpec
{
GTypeInstance g_instance;
gchar *name;
gchar *nick;
gchar *blurb;
GParamFlags flags;
/*< private >*/
GType owner_type;
GData *qdata;
guint ref_count;
};
/* --- prototypes --- */ /* --- prototypes --- */
GParamSpec* g_param_spec_ref (GParamSpec *pspec); GParamSpec* g_param_spec_ref (GParamSpec *pspec);
void g_param_spec_unref (GParamSpec *pspec); void g_param_spec_unref (GParamSpec *pspec);
void g_param_spec_sink (GParamSpec *pspec);
gpointer g_param_spec_get_qdata (GParamSpec *pspec, gpointer g_param_spec_get_qdata (GParamSpec *pspec,
GQuark quark); GQuark quark);
void g_param_spec_set_qdata (GParamSpec *pspec, void g_param_spec_set_qdata (GParamSpec *pspec,
@ -111,6 +114,10 @@ gboolean g_param_value_validate (GParamSpec *pspec,
gint g_param_values_cmp (GParamSpec *pspec, gint g_param_values_cmp (GParamSpec *pspec,
const GValue *value1, const GValue *value1,
const GValue *value2); const GValue *value2);
void g_value_set_param (GValue *value,
GParamSpec *param);
GParamSpec* g_value_get_param (const GValue *value);
GParamSpec* g_value_dup_param (const GValue *value);
/* --- convenience functions --- */ /* --- convenience functions --- */

View File

@ -540,6 +540,103 @@ param_string_values_cmp (GParamSpec *pspec,
return strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer); return strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
} }
static void
param_spec_param_init (GParamSpec *pspec)
{
GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec);
spec->param_type = G_TYPE_PARAM;
}
static void
param_param_set_default (GParamSpec *pspec,
GValue *value)
{
value->data[0].v_pointer = NULL;
}
static gboolean
param_param_validate (GParamSpec *pspec,
GValue *value)
{
GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec);
GParamSpec *param = value->data[0].v_pointer;
guint changed = 0;
if (param && !g_type_is_a (G_PARAM_SPEC_TYPE (param), spec->param_type))
{
g_param_spec_unref (param);
value->data[0].v_pointer = NULL;
changed++;
}
return changed;
}
static void
param_spec_pointer_init (GParamSpec *pspec)
{
/* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
}
static void
param_pointer_set_default (GParamSpec *pspec,
GValue *value)
{
value->data[0].v_pointer = NULL;
}
static gboolean
param_pointer_validate (GParamSpec *pspec,
GValue *value)
{
/* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
guint changed = 0;
return changed;
}
static gint
param_pointer_values_cmp (GParamSpec *pspec,
const GValue *value1,
const GValue *value2)
{
return value1->data[0].v_pointer != value2->data[0].v_pointer;
}
static void
param_spec_ccallback_init (GParamSpec *pspec)
{
/* GParamSpecCCallback *spec = G_PARAM_SPEC_CCALLBACK (pspec); */
}
static void
param_ccallback_set_default (GParamSpec *pspec,
GValue *value)
{
value->data[0].v_pointer = NULL;
value->data[1].v_pointer = NULL;
}
static gboolean
param_ccallback_validate (GParamSpec *pspec,
GValue *value)
{
/* GParamSpecCCallback *spec = G_PARAM_SPEC_CCALLBACK (pspec); */
guint changed = 0;
return changed;
}
static gint
param_ccallback_values_cmp (GParamSpec *pspec,
const GValue *value1,
const GValue *value2)
{
return (value1->data[0].v_pointer != value2->data[0].v_pointer ||
value1->data[1].v_pointer != value2->data[1].v_pointer);
}
static void static void
param_spec_object_init (GParamSpec *pspec) param_spec_object_init (GParamSpec *pspec)
{ {
@ -919,6 +1016,57 @@ g_param_spec_types_init (void) /* sync with gtype.c */
g_assert (type == G_TYPE_PARAM_STRING); g_assert (type == G_TYPE_PARAM_STRING);
} }
/* G_TYPE_PARAM_PARAM
*/
{
static const GParamSpecTypeInfo pspec_info = {
sizeof (GParamSpecParam), /* instance_size */
16, /* n_preallocs */
param_spec_param_init, /* instance_init */
G_TYPE_PARAM, /* value_type */
NULL, /* finalize */
param_param_set_default, /* value_set_default */
param_param_validate, /* value_validate */
param_pointer_values_cmp, /* values_cmp */
};
type = g_param_type_register_static ("GParamParam", &pspec_info);
g_assert (type == G_TYPE_PARAM_PARAM);
}
/* G_TYPE_PARAM_POINTER
*/
{
static const GParamSpecTypeInfo pspec_info = {
sizeof (GParamSpecPointer), /* instance_size */
0, /* n_preallocs */
param_spec_pointer_init, /* instance_init */
G_TYPE_POINTER, /* value_type */
NULL, /* finalize */
param_pointer_set_default, /* value_set_default */
param_pointer_validate, /* value_validate */
param_pointer_values_cmp, /* values_cmp */
};
type = g_param_type_register_static ("GParamPointer", &pspec_info);
g_assert (type == G_TYPE_PARAM_POINTER);
}
/* G_TYPE_PARAM_CCALLBACK
*/
{
static const GParamSpecTypeInfo pspec_info = {
sizeof (GParamSpecCCallback), /* instance_size */
0, /* n_preallocs */
param_spec_ccallback_init, /* instance_init */
G_TYPE_CCALLBACK, /* value_type */
NULL, /* finalize */
param_ccallback_set_default, /* value_set_default */
param_ccallback_validate, /* value_validate */
param_ccallback_values_cmp, /* values_cmp */
};
type = g_param_type_register_static ("GParamCCallback", &pspec_info);
g_assert (type == G_TYPE_PARAM_CCALLBACK);
}
/* G_TYPE_PARAM_OBJECT /* G_TYPE_PARAM_OBJECT
*/ */
{ {
@ -1280,6 +1428,59 @@ g_param_spec_string_c (const gchar *name,
return G_PARAM_SPEC (sspec); return G_PARAM_SPEC (sspec);
} }
GParamSpec*
g_param_spec_param (const gchar *name,
const gchar *nick,
const gchar *blurb,
GType param_type,
GParamFlags flags)
{
GParamSpecParam *pspec;
g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
name,
nick,
blurb,
flags);
pspec->param_type = param_type;
return G_PARAM_SPEC (pspec);
}
GParamSpec*
g_param_spec_pointer (const gchar *name,
const gchar *nick,
const gchar *blurb,
GParamFlags flags)
{
GParamSpecPointer *pspec;
pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
name,
nick,
blurb,
flags);
return G_PARAM_SPEC (pspec);
}
GParamSpec*
g_param_spec_ccallback (const gchar *name,
const gchar *nick,
const gchar *blurb,
GParamFlags flags)
{
GParamSpecCCallback *cspec;
cspec = g_param_spec_internal (G_TYPE_PARAM_CCALLBACK,
name,
nick,
blurb,
flags);
return G_PARAM_SPEC (cspec);
}
GParamSpec* GParamSpec*
g_param_spec_object (const gchar *name, g_param_spec_object (const gchar *name,
const gchar *nick, const gchar *nick,

View File

@ -33,48 +33,57 @@ extern "C" {
/* --- type macros --- */ /* --- type macros --- */
#define G_IS_PARAM_SPEC_CHAR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CHAR)) #define G_IS_PARAM_SPEC_CHAR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CHAR))
#define G_PARAM_SPEC_CHAR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CHAR, GParamSpecChar)) #define G_PARAM_SPEC_CHAR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CHAR, GParamSpecChar))
#define G_IS_PARAM_SPEC_UCHAR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UCHAR)) #define G_IS_PARAM_SPEC_UCHAR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UCHAR))
#define G_PARAM_SPEC_UCHAR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UCHAR, GParamSpecUChar)) #define G_PARAM_SPEC_UCHAR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UCHAR, GParamSpecUChar))
#define G_IS_PARAM_SPEC_BOOLEAN(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_BOOLEAN)) #define G_IS_PARAM_SPEC_BOOLEAN(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_BOOLEAN))
#define G_PARAM_SPEC_BOOLEAN(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_BOOLEAN, GParamSpecBoolean)) #define G_PARAM_SPEC_BOOLEAN(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_BOOLEAN, GParamSpecBoolean))
#define G_IS_PARAM_SPEC_INT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_INT)) #define G_IS_PARAM_SPEC_INT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_INT))
#define G_PARAM_SPEC_INT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_INT, GParamSpecInt)) #define G_PARAM_SPEC_INT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_INT, GParamSpecInt))
#define G_IS_PARAM_SPEC_UINT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UINT)) #define G_IS_PARAM_SPEC_UINT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UINT))
#define G_PARAM_SPEC_UINT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UINT, GParamSpecUInt)) #define G_PARAM_SPEC_UINT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UINT, GParamSpecUInt))
#define G_IS_PARAM_SPEC_LONG(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_LONG)) #define G_IS_PARAM_SPEC_LONG(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_LONG))
#define G_PARAM_SPEC_LONG(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_LONG, GParamSpecLong)) #define G_PARAM_SPEC_LONG(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_LONG, GParamSpecLong))
#define G_IS_PARAM_SPEC_ULONG(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ULONG)) #define G_IS_PARAM_SPEC_ULONG(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ULONG))
#define G_PARAM_SPEC_ULONG(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ULONG, GParamSpecULong)) #define G_PARAM_SPEC_ULONG(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ULONG, GParamSpecULong))
#define G_IS_PARAM_SPEC_ENUM(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ENUM)) #define G_IS_PARAM_SPEC_ENUM(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ENUM))
#define G_PARAM_SPEC_ENUM(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ENUM, GParamSpecEnum)) #define G_PARAM_SPEC_ENUM(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ENUM, GParamSpecEnum))
#define G_IS_PARAM_SPEC_FLAGS(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLAGS)) #define G_IS_PARAM_SPEC_FLAGS(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLAGS))
#define G_PARAM_SPEC_FLAGS(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLAGS, GParamSpecFlags)) #define G_PARAM_SPEC_FLAGS(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLAGS, GParamSpecFlags))
#define G_IS_PARAM_SPEC_FLOAT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLOAT)) #define G_IS_PARAM_SPEC_FLOAT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLOAT))
#define G_PARAM_SPEC_FLOAT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLOAT, GParamSpecFloat)) #define G_PARAM_SPEC_FLOAT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLOAT, GParamSpecFloat))
#define G_IS_PARAM_SPEC_DOUBLE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_DOUBLE)) #define G_IS_PARAM_SPEC_DOUBLE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_DOUBLE))
#define G_PARAM_SPEC_DOUBLE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_DOUBLE, GParamSpecDouble)) #define G_PARAM_SPEC_DOUBLE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_DOUBLE, GParamSpecDouble))
#define G_IS_PARAM_SPEC_STRING(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_STRING)) #define G_IS_PARAM_SPEC_STRING(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_STRING))
#define G_PARAM_SPEC_STRING(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_STRING, GParamSpecString)) #define G_PARAM_SPEC_STRING(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_STRING, GParamSpecString))
#define G_IS_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT)) #define G_IS_PARAM_SPEC_PARAM(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_PARAM))
#define G_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject)) #define G_PARAM_SPEC_PARAM(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_PARAM, GParamSpecParam))
#define G_IS_PARAM_SPEC_POINTER(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_POINTER))
#define G_PARAM_SPEC_POINTER(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_POINTER, GParamSpecPointer))
#define G_IS_PARAM_SPEC_CCALLBACK(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CCALLBACK))
#define G_PARAM_SPEC_CCALLBACK(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CCALLBACK, GParamSpecCCallback))
#define G_IS_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT))
#define G_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject))
/* --- typedefs & structures --- */ /* --- typedefs & structures --- */
typedef struct _GParamSpecChar GParamSpecChar; typedef struct _GParamSpecChar GParamSpecChar;
typedef struct _GParamSpecUChar GParamSpecUChar; typedef struct _GParamSpecUChar GParamSpecUChar;
typedef struct _GParamSpecBoolean GParamSpecBoolean; typedef struct _GParamSpecBoolean GParamSpecBoolean;
typedef struct _GParamSpecInt GParamSpecInt; typedef struct _GParamSpecInt GParamSpecInt;
typedef struct _GParamSpecUInt GParamSpecUInt; typedef struct _GParamSpecUInt GParamSpecUInt;
typedef struct _GParamSpecLong GParamSpecLong; typedef struct _GParamSpecLong GParamSpecLong;
typedef struct _GParamSpecULong GParamSpecULong; typedef struct _GParamSpecULong GParamSpecULong;
typedef struct _GParamSpecEnum GParamSpecEnum; typedef struct _GParamSpecEnum GParamSpecEnum;
typedef struct _GParamSpecFlags GParamSpecFlags; typedef struct _GParamSpecFlags GParamSpecFlags;
typedef struct _GParamSpecFloat GParamSpecFloat; typedef struct _GParamSpecFloat GParamSpecFloat;
typedef struct _GParamSpecDouble GParamSpecDouble; typedef struct _GParamSpecDouble GParamSpecDouble;
typedef struct _GParamSpecString GParamSpecString; typedef struct _GParamSpecString GParamSpecString;
typedef struct _GParamSpecObject GParamSpecObject; typedef struct _GParamSpecParam GParamSpecParam;
typedef struct _GParamSpecPointer GParamSpecPointer;
typedef struct _GParamSpecCCallback GParamSpecCCallback;
typedef struct _GParamSpecObject GParamSpecObject;
struct _GParamSpecChar struct _GParamSpecChar
{ {
GParamSpec parent_instance; GParamSpec parent_instance;
@ -172,6 +181,20 @@ struct _GParamSpecString
guint null_fold_if_empty : 1; guint null_fold_if_empty : 1;
guint ensure_non_null : 1; guint ensure_non_null : 1;
}; };
struct _GParamSpecParam
{
GParamSpec parent_instance;
GType param_type;
};
struct _GParamSpecPointer
{
GParamSpec parent_instance;
};
struct _GParamSpecCCallback
{
GParamSpec parent_instance;
};
struct _GParamSpecObject struct _GParamSpecObject
{ {
GParamSpec parent_instance; GParamSpec parent_instance;
@ -264,6 +287,19 @@ GParamSpec* g_param_spec_string_c (const gchar *name,
const gchar *blurb, const gchar *blurb,
const gchar *default_value, const gchar *default_value,
GParamFlags flags); GParamFlags flags);
GParamSpec* g_param_spec_param (const gchar *name,
const gchar *nick,
const gchar *blurb,
GType param_type,
GParamFlags flags);
GParamSpec* g_param_spec_pointer (const gchar *name,
const gchar *nick,
const gchar *blurb,
GParamFlags flags);
GParamSpec* g_param_spec_ccallback (const gchar *name,
const gchar *nick,
const gchar *blurb,
GParamFlags flags);
GParamSpec* g_param_spec_object (const gchar *name, GParamSpec* g_param_spec_object (const gchar *name,
const gchar *nick, const gchar *nick,
const gchar *blurb, const gchar *blurb,

View File

@ -22,12 +22,13 @@
#include <string.h> #include <string.h>
#include "gsignal.h" #include "gsignal.h"
#include "gbsearcharray.h" #include "gbsearcharray.h"
#include "gvaluecollector.h"
/* pre allocation configurations /* pre allocation configurations
*/ */
#define MAX_STACK_VALUES (16)
#define BSA_PRE_ALLOC (20) #define BSA_PRE_ALLOC (20)
#define HANDLER_PRE_ALLOC (48) #define HANDLER_PRE_ALLOC (48)
#define EMISSION_PRE_ALLOC (16) #define EMISSION_PRE_ALLOC (16)
@ -131,7 +132,7 @@ static inline Emission* emission_find (Emission *emission_list,
guint signal_id, guint signal_id,
GQuark detail, GQuark detail,
gpointer instance); gpointer instance);
static void signal_emit_R (SignalNode *node, static gboolean signal_emit_R (SignalNode *node,
GQuark detail, GQuark detail,
gpointer instance, gpointer instance,
GValue *return_value, GValue *return_value,
@ -233,21 +234,43 @@ static inline guint
signal_id_lookup (GQuark quark, signal_id_lookup (GQuark quark,
GType itype) GType itype)
{ {
GType *ifaces, type = itype;
SignalKey key;
guint n_ifaces;
key.quark = quark;
/* try looking up signals for this type and its anchestors */
do do
{ {
SignalKey key, *signal_key; SignalKey *signal_key;
key.itype = itype;
key.quark = quark;
key.itype = type;
signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key); signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
if (signal_key) if (signal_key)
return signal_key->signal_id; return signal_key->signal_id;
itype = g_type_parent (itype); type = g_type_parent (type);
} }
while (itype); while (type);
/* no luck, try interfaces it exports */
ifaces = g_type_interfaces (itype, &n_ifaces);
while (n_ifaces--)
{
SignalKey *signal_key;
key.itype = ifaces[n_ifaces];
signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
if (signal_key)
{
g_free (ifaces);
return signal_key->signal_id;
}
}
g_free (ifaces);
return 0; return 0;
} }
@ -515,7 +538,7 @@ handler_insert (guint signal_id,
{ {
HandlerList *hlist; HandlerList *hlist;
g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
hlist = handler_list_ensure (signal_id, instance); hlist = handler_list_ensure (signal_id, instance);
if (!hlist->handlers) if (!hlist->handlers)
@ -671,7 +694,7 @@ g_signal_stop_emission (gpointer instance,
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
return; return;
} }
if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype)) if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
{ {
Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
Emission *emission = emission_find (emission_list, signal_id, detail, instance); Emission *emission = emission_find (emission_list, signal_id, detail, instance);
@ -859,6 +882,44 @@ g_signal_list_ids (GType itype,
return (guint *) g_array_free (result, FALSE); return (guint *) g_array_free (result, FALSE);
} }
guint
g_signal_new (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
GClosure *class_closure,
GSignalAccumulator accumulator,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
...)
{
GType *param_types;
guint i;
va_list args;
guint signal_id;
if (n_params > 0)
{
param_types = g_new (GType, n_params);
va_start (args, n_params);
for (i = 0; i < n_params; i++)
param_types[i] = va_arg (args, GType);
va_end (args);
}
else
param_types = NULL;
signal_id = g_signal_newv (signal_name, itype, signal_flags,
class_closure, accumulator, c_marshaller,
return_type, n_params, param_types);
g_free (param_types);
return signal_id;
}
guint guint
g_signal_newv (const gchar *signal_name, g_signal_newv (const gchar *signal_name,
GType itype, GType itype,
@ -1023,22 +1084,23 @@ g_signal_connect_closure_by_id (gpointer instance,
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
node = LOOKUP_SIGNAL_NODE (signal_id); node = LOOKUP_SIGNAL_NODE (signal_id);
if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) if (node)
{ {
g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); if (detail && !(node->flags & G_SIGNAL_DETAILED))
G_UNLOCK (g_signal_mutex); g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
return 0; else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
} g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype)) else
{ {
Handler *handler = handler_new (after); Handler *handler = handler_new (after);
handler_id = handler->id; handler_id = handler->id;
handler->detail = detail; handler->detail = detail;
handler->closure = g_closure_ref (closure); handler->closure = g_closure_ref (closure);
handler_insert (signal_id, instance, handler); handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
g_closure_set_marshal (closure, node->c_marshaller); g_closure_set_marshal (closure, node->c_marshaller);
}
} }
else else
g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
@ -1047,6 +1109,97 @@ g_signal_connect_closure_by_id (gpointer instance,
return handler_id; return handler_id;
} }
guint
g_signal_connect_closure (gpointer instance,
const gchar *detailed_signal,
GClosure *closure,
gboolean after)
{
guint signal_id, handler_id = 0;
GQuark detail = 0;
GType itype;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
g_return_val_if_fail (detailed_signal != NULL, 0);
g_return_val_if_fail (closure != NULL, 0);
G_LOCK (g_signal_mutex);
itype = G_TYPE_FROM_INSTANCE (instance);
signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
if (signal_id)
{
SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
if (detail && !(node->flags & G_SIGNAL_DETAILED))
g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
else if (!g_type_is_a (itype, node->itype))
g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
else
{
Handler *handler = handler_new (after);
handler_id = handler->id;
handler->detail = detail;
handler->closure = g_closure_ref (closure);
handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
g_closure_set_marshal (handler->closure, node->c_marshaller);
}
}
else
g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
G_UNLOCK (g_signal_mutex);
return handler_id;
}
guint
g_signal_connect_data (gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
gboolean swapped,
gboolean after)
{
guint signal_id, handler_id = 0;
GQuark detail = 0;
GType itype;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
g_return_val_if_fail (detailed_signal != NULL, 0);
g_return_val_if_fail (c_handler != NULL, 0);
G_LOCK (g_signal_mutex);
itype = G_TYPE_FROM_INSTANCE (instance);
signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
if (signal_id)
{
SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
if (detail && !(node->flags & G_SIGNAL_DETAILED))
g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
else if (!g_type_is_a (itype, node->itype))
g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
else
{
Handler *handler = handler_new (after);
handler_id = handler->id;
handler->detail = detail;
handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
g_closure_set_marshal (handler->closure, node->c_marshaller);
}
}
else
g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
G_UNLOCK (g_signal_mutex);
return handler_id;
}
void void
g_signal_handler_block (gpointer instance, g_signal_handler_block (gpointer instance,
guint handler_id) guint handler_id)
@ -1342,9 +1495,9 @@ g_signal_emitv (const GValue *instance_and_params,
GQuark detail, GQuark detail,
GValue *return_value) GValue *return_value)
{ {
SignalNode *node;
gpointer instance;
const GValue *param_values; const GValue *param_values;
gpointer instance;
SignalNode *node;
guint i; guint i;
g_return_if_fail (instance_and_params != NULL); g_return_if_fail (instance_and_params != NULL);
@ -1356,13 +1509,13 @@ g_signal_emitv (const GValue *instance_and_params,
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
node = LOOKUP_SIGNAL_NODE (signal_id); node = LOOKUP_SIGNAL_NODE (signal_id);
#ifndef G_DISABLE_CHECKS if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
{ {
g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
return; return;
} }
#ifndef G_DISABLE_CHECKS
if (detail && !(node->flags & G_SIGNAL_DETAILED)) if (detail && !(node->flags & G_SIGNAL_DETAILED))
{ {
g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
@ -1372,7 +1525,8 @@ g_signal_emitv (const GValue *instance_and_params,
for (i = 0; i < node->n_params; i++) for (i = 0; i < node->n_params; i++)
if (!G_VALUE_HOLDS (param_values + i, node->param_types[i])) if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
{ {
g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'", g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
G_STRLOC,
g_type_name (node->param_types[i]), g_type_name (node->param_types[i]),
i, i,
node->name, node->name,
@ -1384,7 +1538,8 @@ g_signal_emitv (const GValue *instance_and_params,
{ {
if (!return_value) if (!return_value)
{ {
g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)", g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
G_STRLOC,
g_type_name (node->return_type), g_type_name (node->return_type),
node->name); node->name);
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
@ -1392,7 +1547,8 @@ g_signal_emitv (const GValue *instance_and_params,
} }
else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type)) else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
{ {
g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'", g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
G_STRLOC,
g_type_name (node->return_type), g_type_name (node->return_type),
node->name, node->name,
G_VALUE_TYPE_NAME (return_value)); G_VALUE_TYPE_NAME (return_value));
@ -1405,11 +1561,145 @@ g_signal_emitv (const GValue *instance_and_params,
#endif /* !G_DISABLE_CHECKS */ #endif /* !G_DISABLE_CHECKS */
signal_emit_R (node, detail, instance, return_value, instance_and_params); signal_emit_R (node, detail, instance, return_value, instance_and_params);
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
} }
static void void
g_signal_emit_valist (gpointer instance,
guint signal_id,
GQuark detail,
va_list var_args)
{
GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
GValue *param_values;
SignalNode *node;
guint i;
g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
g_return_if_fail (signal_id > 0);
G_LOCK (g_signal_mutex);
node = LOOKUP_SIGNAL_NODE (signal_id);
if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
{
g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
G_UNLOCK (g_signal_mutex);
return;
}
#ifndef G_DISABLE_CHECKS
if (detail && !(node->flags & G_SIGNAL_DETAILED))
{
g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
G_UNLOCK (g_signal_mutex);
return;
}
#endif /* !G_DISABLE_CHECKS */
if (node->n_params < MAX_STACK_VALUES)
instance_and_params = stack_values;
else
{
free_me = g_new (GValue, node->n_params + 1);
instance_and_params = free_me;
}
param_values = instance_and_params + 1;
for (i = 0; i < node->n_params; i++)
{
gchar *error;
param_values[i].g_type = 0;
g_value_init (param_values + i, node->param_types[i]);
G_VALUE_COLLECT (param_values + i, var_args, &error);
if (error)
{
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
/* we purposely leak the value here, it might not be
* in a sane state if an error condition occoured
*/
while (i--)
g_value_unset (param_values + i);
G_UNLOCK (g_signal_mutex);
g_free (free_me);
return;
}
}
instance_and_params->g_type = 0;
g_value_init (instance_and_params, node->itype);
g_value_set_instance (instance_and_params, instance);
if (node->return_type == G_TYPE_NONE)
signal_emit_R (node, detail, instance, NULL, instance_and_params);
else
{
GValue return_value = { 0, };
gchar *error = NULL;
g_value_init (&return_value, node->return_type);
if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
G_VALUE_LCOPY (&return_value, var_args, &error);
if (!error)
g_value_unset (&return_value);
else
{
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
/* we purposely leak the value here, it might not be
* in a sane state if an error condition occoured
*/
}
}
for (i = 0; i < node->n_params; i++)
g_value_unset (param_values + i);
g_value_unset (instance_and_params);
if (free_me)
g_free (free_me);
G_UNLOCK (g_signal_mutex);
}
void
g_signal_emit (gpointer instance,
guint signal_id,
GQuark detail,
...)
{
va_list var_args;
va_start (var_args, detail);
g_signal_emit_valist (instance, signal_id, detail, var_args);
va_end (var_args);
}
void
g_signal_emit_by_name (gpointer instance,
const gchar *detailed_signal,
...)
{
GQuark detail = 0;
guint signal_id;
g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
g_return_if_fail (detailed_signal != NULL);
G_LOCK (g_signal_mutex);
signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
G_UNLOCK (g_signal_mutex);
if (signal_id)
{
va_list var_args;
va_start (var_args, detailed_signal);
g_signal_emit_valist (instance, signal_id, detail, var_args);
va_end (var_args);
}
else
g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
}
static gboolean
signal_emit_R (SignalNode *node, signal_emit_R (SignalNode *node,
GQuark detail, GQuark detail,
gpointer instance, gpointer instance,
@ -1422,9 +1712,10 @@ signal_emit_R (SignalNode *node,
GClosure *class_closure; GClosure *class_closure;
HandlerList *hlist; HandlerList *hlist;
Handler *handler_list = NULL; Handler *handler_list = NULL;
GValue accu; GValue accu = { 0, };
gboolean accu_used = FALSE; gboolean accu_used = FALSE;
guint signal_id = node->signal_id; guint signal_id = node->signal_id;
gboolean return_value_altered = FALSE;
if (node->flags & G_SIGNAL_NO_RECURSE) if (node->flags & G_SIGNAL_NO_RECURSE)
{ {
@ -1433,18 +1724,14 @@ signal_emit_R (SignalNode *node,
if (emission) if (emission)
{ {
*emission->state_p = EMISSION_RESTART; *emission->state_p = EMISSION_RESTART;
return; return return_value_altered;
} }
} }
ihint.signal_id = node->signal_id; ihint.signal_id = node->signal_id;
ihint.detail = detail; ihint.detail = detail;
accumulator = node->accumulator; accumulator = node->accumulator;
if (accumulator) if (accumulator)
{ g_value_init (&accu, node->return_type);
G_UNLOCK (g_signal_mutex);
g_value_init (&accu, node->return_type);
G_LOCK (g_signal_mutex);
}
emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
signal_id, detail, instance, &emission_state); signal_id, detail, instance, &emission_state);
class_closure = node->class_closure; class_closure = node->class_closure;
@ -1486,6 +1773,7 @@ signal_emit_R (SignalNode *node,
instance_and_params, instance_and_params,
&ihint); &ihint);
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
if (emission_state == EMISSION_STOP) if (emission_state == EMISSION_STOP)
goto EMIT_CLEANUP; goto EMIT_CLEANUP;
@ -1545,6 +1833,7 @@ signal_emit_R (SignalNode *node,
instance_and_params, instance_and_params,
&ihint); &ihint);
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
tmp = emission_state == EMISSION_RUN ? handler->next : NULL; tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
} }
@ -1593,6 +1882,7 @@ signal_emit_R (SignalNode *node,
instance_and_params, instance_and_params,
&ihint); &ihint);
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
if (emission_state == EMISSION_STOP) if (emission_state == EMISSION_STOP)
goto EMIT_CLEANUP; goto EMIT_CLEANUP;
@ -1634,6 +1924,7 @@ signal_emit_R (SignalNode *node,
instance_and_params, instance_and_params,
&ihint); &ihint);
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
tmp = emission_state == EMISSION_RUN ? handler->next : NULL; tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
} }
@ -1692,9 +1983,12 @@ signal_emit_R (SignalNode *node,
emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state); emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
if (accumulator) if (accumulator)
{ g_value_unset (&accu);
G_UNLOCK (g_signal_mutex);
g_value_unset (&accu); return return_value_altered;
G_LOCK (g_signal_mutex);
}
} }
/* compile standard marshallers */
#include "gvaluetypes.h"
#include "gmarshal.c"

View File

@ -23,6 +23,7 @@
#include <gobject/gclosure.h> #include <gobject/gclosure.h>
#include <gobject/gvalue.h> #include <gobject/gvalue.h>
#include <gobject/gparam.h> #include <gobject/gparam.h>
#include <gobject/gmarshal.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -86,9 +87,18 @@ struct _GSignalQuery
/* --- signals --- */ /* --- signals --- */
guint g_signal_new (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
GClosure *class_closure,
GSignalAccumulator accumulator,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
...);
guint g_signal_newv (const gchar *signal_name, guint g_signal_newv (const gchar *signal_name,
GType itype, GType itype,
GSignalFlags signal_flags, GSignalFlags signal_flags,
GClosure *class_closure, GClosure *class_closure,
GSignalAccumulator accumulator, GSignalAccumulator accumulator,
GSignalCMarshaller c_marshaller, GSignalCMarshaller c_marshaller,
@ -99,6 +109,17 @@ void g_signal_emitv (const GValue *instance_and_params,
guint signal_id, guint signal_id,
GQuark detail, GQuark detail,
GValue *return_value); GValue *return_value);
void g_signal_emit_valist (gpointer instance,
guint signal_id,
GQuark detail,
va_list var_args);
void g_signal_emit (gpointer instance,
guint signal_id,
GQuark detail,
...);
void g_signal_emit_by_name (gpointer instance,
const gchar *detailed_signal,
...);
guint g_signal_lookup (const gchar *name, guint g_signal_lookup (const gchar *name,
GType itype); GType itype);
gchar* g_signal_name (guint signal_id); gchar* g_signal_name (guint signal_id);
@ -127,6 +148,17 @@ guint g_signal_connect_closure_by_id (gpointer instance,
GQuark detail, GQuark detail,
GClosure *closure, GClosure *closure,
gboolean after); gboolean after);
guint g_signal_connect_closure (gpointer instance,
const gchar *detailed_signal,
GClosure *closure,
gboolean after);
guint g_signal_connect_data (gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
gboolean swapped,
gboolean after);
void g_signal_handler_block (gpointer instance, void g_signal_handler_block (gpointer instance,
guint handler_id); guint handler_id);
void g_signal_handler_unblock (gpointer instance, void g_signal_handler_unblock (gpointer instance,

View File

@ -21,7 +21,7 @@
#include "gtypeplugin.h" #include "gtypeplugin.h"
#include <string.h> #include <string.h>
#define FIXME_DISABLE_PREALLOCATIONS #undef FIXME_DISABLE_PREALLOCATIONS
/* NOTE: some functions (some internal variants and exported ones) /* NOTE: some functions (some internal variants and exported ones)
* invalidate data portions of the TypeNodes. if external functions/callbacks * invalidate data portions of the TypeNodes. if external functions/callbacks
@ -173,7 +173,7 @@ static GQuark quark_type_flags = 0;
/* --- externs --- */ /* --- externs --- */
const char *g_log_domain_gobject = "GLib-Object"; const char *g_log_domain_gruntime = "GRuntime";
/* --- type nodes --- */ /* --- type nodes --- */
@ -796,7 +796,7 @@ type_data_make (TypeNode *node,
*vtable = *value_table; *vtable = *value_table;
node->data->common.value_table = vtable; node->data->common.value_table = vtable;
g_assert (node->data->common.value_table != NULL); /* FIXME: paranoid */ g_assert (node->data->common.value_table != NULL); /* paranoid */
} }
static inline void static inline void
@ -1024,7 +1024,7 @@ g_type_free_instance (GTypeInstance *instance)
} }
instance->g_class = NULL; instance->g_class = NULL;
memset (instance, 0xaa, node->data->instance.instance_size); // FIXME memset (instance, 0xaa, node->data->instance.instance_size); // FIXME: debugging hack
if (node->data->instance.n_preallocs) if (node->data->instance.n_preallocs)
g_chunk_free (instance, node->data->instance.mem_chunk); g_chunk_free (instance, node->data->instance.mem_chunk);
else else
@ -1667,6 +1667,7 @@ g_type_next_base (GType type,
return 0; return 0;
} }
#if 0
gboolean gboolean
g_type_is_a (GType type, g_type_is_a (GType type,
GType is_a_type) GType is_a_type)
@ -1688,10 +1689,11 @@ g_type_is_a (GType type,
return FALSE; return FALSE;
} }
#endif
gboolean gboolean
g_type_conforms_to (GType type, g_type_is_a (GType type,
GType iface_type) GType iface_type)
{ {
if (type != iface_type) if (type != iface_type)
{ {
@ -1807,7 +1809,7 @@ g_type_get_qdata (GType type,
QData *qdatas = gdata->qdatas - 1; QData *qdatas = gdata->qdatas - 1;
guint n_qdatas = gdata->n_qdatas; guint n_qdatas = gdata->n_qdatas;
do /* FIXME: should optimize qdata lookups for <= 4 */ do
{ {
guint i; guint i;
QData *check; QData *check;
@ -1943,12 +1945,12 @@ g_type_fundamental_last (void)
} }
gboolean gboolean
g_type_instance_conforms_to (GTypeInstance *type_instance, g_type_instance_is_a (GTypeInstance *type_instance,
GType iface_type) GType iface_type)
{ {
return (type_instance && type_instance->g_class && return (type_instance && type_instance->g_class &&
G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type) && G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type) &&
g_type_conforms_to (type_instance->g_class->g_type, iface_type)); g_type_is_a (type_instance->g_class->g_type, iface_type));
} }
gboolean gboolean
@ -1960,8 +1962,8 @@ g_type_class_is_a (GTypeClass *type_class,
} }
gboolean gboolean
g_type_value_conforms_to (GValue *value, g_type_value_is_a (GValue *value,
GType type) GType type)
{ {
TypeNode *node; TypeNode *node;
@ -1974,7 +1976,7 @@ g_type_value_conforms_to (GValue *value,
#endif #endif
if (!node || !node->data || node->data->common.ref_count < 1 || if (!node || !node->data || node->data->common.ref_count < 1 ||
!node->data->common.value_table->value_init || !node->data->common.value_table->value_init ||
!g_type_conforms_to (value->g_type, type)) !g_type_is_a (value->g_type, type))
return FALSE; return FALSE;
return TRUE; return TRUE;
@ -1983,7 +1985,7 @@ g_type_value_conforms_to (GValue *value,
gboolean gboolean
g_type_check_value (GValue *value) g_type_check_value (GValue *value)
{ {
return value && g_type_value_conforms_to (value, value->g_type); return value && g_type_value_is_a (value, value->g_type);
} }
GTypeInstance* GTypeInstance*
@ -2009,7 +2011,7 @@ g_type_check_instance_cast (GTypeInstance *type_instance,
type_descriptive_name (iface_type)); type_descriptive_name (iface_type));
return type_instance; return type_instance;
} }
if (!g_type_conforms_to (type_instance->g_class->g_type, iface_type)) if (!g_type_is_a (type_instance->g_class->g_type, iface_type))
{ {
g_warning ("invalid cast from `%s' to `%s'", g_warning ("invalid cast from `%s' to `%s'",
type_descriptive_name (type_instance->g_class->g_type), type_descriptive_name (type_instance->g_class->g_type),
@ -2125,7 +2127,7 @@ g_type_init (void)
memset (&info, 0, sizeof (info)); memset (&info, 0, sizeof (info));
node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE); node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
type = NODE_TYPE (node); type = NODE_TYPE (node);
type_data_make (node, &info, NULL); /* FIXME */ type_data_make (node, &info, NULL);
g_assert (type == G_TYPE_INTERFACE); g_assert (type == G_TYPE_INTERFACE);
/* G_TYPE_TYPE_PLUGIN /* G_TYPE_TYPE_PLUGIN

View File

@ -19,7 +19,7 @@
#ifndef __G_TYPE_H__ #ifndef __G_TYPE_H__
#define __G_TYPE_H__ #define __G_TYPE_H__
extern const char *g_log_domain_gobject; extern const char *g_log_domain_gruntime;
#include <glib.h> #include <glib.h>
@ -62,6 +62,7 @@ typedef enum /*< skip >*/
G_TYPE_PARAM, G_TYPE_PARAM,
G_TYPE_BOXED, G_TYPE_BOXED,
G_TYPE_POINTER, G_TYPE_POINTER,
G_TYPE_CCALLBACK,
G_TYPE_OBJECT, G_TYPE_OBJECT,
/* the following reserved ids should vanish soon */ /* the following reserved ids should vanish soon */
@ -79,7 +80,6 @@ typedef enum /*< skip >*/
G_TYPE_LAST_RESERVED_FUNDAMENTAL, G_TYPE_LAST_RESERVED_FUNDAMENTAL,
/* derived type ids */ /* derived type ids */
/* FIXME: G_TYPE_PARAM_INTERFACE */
G_TYPE_PARAM_CHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 1), G_TYPE_PARAM_CHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 1),
G_TYPE_PARAM_UCHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 2), G_TYPE_PARAM_UCHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 2),
G_TYPE_PARAM_BOOLEAN = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 3), G_TYPE_PARAM_BOOLEAN = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 3),
@ -92,8 +92,10 @@ typedef enum /*< skip >*/
G_TYPE_PARAM_FLOAT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 10), G_TYPE_PARAM_FLOAT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 10),
G_TYPE_PARAM_DOUBLE = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 11), G_TYPE_PARAM_DOUBLE = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 11),
G_TYPE_PARAM_STRING = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 12), G_TYPE_PARAM_STRING = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 12),
/* FIXME: G_TYPE_PARAM_PARAM */ G_TYPE_PARAM_PARAM = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 13),
G_TYPE_PARAM_OBJECT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 13) G_TYPE_PARAM_POINTER = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 14),
G_TYPE_PARAM_CCALLBACK = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 15),
G_TYPE_PARAM_OBJECT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 16)
} GTypeFundamentals; } GTypeFundamentals;
@ -174,8 +176,6 @@ GType g_type_next_base (GType type,
GType base_type); GType base_type);
gboolean g_type_is_a (GType type, gboolean g_type_is_a (GType type,
GType is_a_type); GType is_a_type);
gboolean g_type_conforms_to (GType type,
GType iface_type);
guint g_type_fundamental_branch_last (GType type); guint g_type_fundamental_branch_last (GType type);
gpointer g_type_class_ref (GType type); gpointer g_type_class_ref (GType type);
gpointer g_type_class_peek (GType type); gpointer g_type_class_peek (GType type);
@ -317,10 +317,10 @@ gboolean g_type_class_is_a (GTypeClass *g_class,
GType is_a_type); GType is_a_type);
GTypeInstance* g_type_check_instance_cast (GTypeInstance *instance, GTypeInstance* g_type_check_instance_cast (GTypeInstance *instance,
GType iface_type); GType iface_type);
gboolean g_type_instance_conforms_to (GTypeInstance *instance, gboolean g_type_instance_is_a (GTypeInstance *instance,
GType iface_type); GType iface_type);
gboolean g_type_check_value (GValue *value); gboolean g_type_check_value (GValue *value);
gboolean g_type_value_conforms_to (GValue *value, gboolean g_type_value_is_a (GValue *value,
GType type); GType type);
gboolean g_type_check_instance (GTypeInstance *instance); gboolean g_type_check_instance (GTypeInstance *instance);
GTypeValueTable* g_type_value_table_peek (GType type); GTypeValueTable* g_type_value_table_peek (GType type);
@ -336,9 +336,9 @@ GTypeValueTable* g_type_value_table_peek (GType type);
# define _G_TYPE_CCC(cp, gt, ct) ((ct*) cp) # define _G_TYPE_CCC(cp, gt, ct) ((ct*) cp)
#endif /* G_DISABLE_CAST_CHECKS */ #endif /* G_DISABLE_CAST_CHECKS */
#define _G_TYPE_CHI(ip) (g_type_check_instance ((GTypeInstance*) ip)) #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_CIT(ip, gt) (g_type_instance_is_a ((GTypeInstance*) ip, gt))
#define _G_TYPE_CCT(cp, gt) (g_type_class_is_a ((GTypeClass*) cp, 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_CVT(vl, gt) (g_type_value_is_a ((GValue*) vl, gt))
#define _G_TYPE_CHV(vl) (g_type_check_value ((GValue*) vl)) #define _G_TYPE_CHV(vl) (g_type_check_value ((GValue*) vl))
#define _G_TYPE_IGC(ip, gt, ct) ((ct*) (((GTypeInstance*) ip)->g_class)) #define _G_TYPE_IGC(ip, gt, ct) ((ct*) (((GTypeInstance*) ip)->g_class))
#define _G_TYPE_IGI(ip, gt, ct) ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt)) #define _G_TYPE_IGI(ip, gt, ct) ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))

View File

@ -406,7 +406,7 @@ g_type_module_add_interface (GTypeModule *module,
g_return_if_fail (module != NULL); g_return_if_fail (module != NULL);
g_return_if_fail (interface_info != NULL); g_return_if_fail (interface_info != NULL);
if (g_type_conforms_to (instance_type, interface_type)) if (g_type_is_a (instance_type, interface_type))
{ {
GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type, GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
interface_type); interface_type);

View File

@ -20,6 +20,7 @@
#include <string.h> #include <string.h>
#include "gvalue.h" #include "gvalue.h"
#include "gvaluecollector.h"
/* --- typedefs & structures --- */ /* --- typedefs & structures --- */
@ -110,6 +111,54 @@ g_value_get_as_pointer (const GValue *value)
return value_table->value_peek_pointer (value); return value_table->value_peek_pointer (value);
} }
void
g_value_set_instance (GValue *value,
gpointer instance)
{
g_return_if_fail (G_IS_VALUE (value));
g_value_reset (value);
if (instance)
{
GType g_type = G_VALUE_TYPE (value);
GTypeValueTable *value_table = g_type_value_table_peek (g_type);
GTypeCValue cvalue = { 0, };
guint nth_value = 0;
guint collect_type = value_table->collect_type;
gchar *error_msg;
g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
g_return_if_fail (g_type_is_a (G_TYPE_FROM_INSTANCE (instance), G_VALUE_TYPE (value)));
g_return_if_fail (value_table->collect_type == G_VALUE_COLLECT_POINTER);
cvalue.v_pointer = instance;
error_msg = value_table->collect_value (value, nth_value++, &collect_type, &cvalue);
/* this shouldn't be triggered, instance types should collect just one pointer,
* but since we have to follow the calling conventions for collect_value(),
* we can attempt to feed them with 0s if they insist on extra args.
*/
while (collect_type && !error_msg)
{
memset (&cvalue, 0, sizeof (cvalue));
error_msg = value_table->collect_value (value, nth_value++, &collect_type, &cvalue);
}
if (error_msg)
{
g_warning ("%s: %s", G_STRLOC, error_msg);
g_free (error_msg);
/* we purposely leak the value here, it might not be
* in a sane state if an error condition occoured
*/
memset (value, 0, sizeof (*value));
value->g_type = g_type;
value_table->value_init (value);
}
}
}
void void
g_value_unset (GValue *value) g_value_unset (GValue *value)
{ {
@ -127,11 +176,12 @@ g_value_unset (GValue *value)
void void
g_value_reset (GValue *value) g_value_reset (GValue *value)
{ {
GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (value)); GTypeValueTable *value_table;
GType g_type; GType g_type;
g_return_if_fail (G_IS_VALUE (value)); g_return_if_fail (G_IS_VALUE (value));
value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
g_type = G_VALUE_TYPE (value); g_type = G_VALUE_TYPE (value);
if (value_table->value_free) if (value_table->value_free)

View File

@ -69,6 +69,8 @@ void g_value_reset (GValue *value);
void g_value_unset (GValue *value); void g_value_unset (GValue *value);
gboolean g_value_fits_pointer (const GValue *value); gboolean g_value_fits_pointer (const GValue *value);
gpointer g_value_get_as_pointer (const GValue *value); gpointer g_value_get_as_pointer (const GValue *value);
void g_value_set_instance (GValue *value,
gpointer instance);
/* --- implementation details --- */ /* --- implementation details --- */

View File

@ -71,9 +71,8 @@ G_STMT_START { \
g_value_reset (_value); \ g_value_reset (_value); \
while (_collect_type && !_error_msg) \ while (_collect_type && !_error_msg) \
{ \ { \
GTypeCValue _cvalue; \ GTypeCValue _cvalue = { 0, }; \
\ \
memset (&_cvalue, 0, sizeof (_cvalue)); \
switch (_collect_type) \ switch (_collect_type) \
{ \ { \
case G_VALUE_COLLECT_INT: \ case G_VALUE_COLLECT_INT: \
@ -117,9 +116,8 @@ G_STMT_START { \
\ \
while (_lcopy_type && !_error_msg) \ while (_lcopy_type && !_error_msg) \
{ \ { \
GTypeCValue _cvalue; \ GTypeCValue _cvalue = { 0, }; \
\ \
memset (&_cvalue, 0, sizeof (_cvalue)); \
switch (_lcopy_type) \ switch (_lcopy_type) \
{ \ { \
case G_VALUE_COLLECT_INT: \ case G_VALUE_COLLECT_INT: \

View File

@ -264,7 +264,7 @@ value_string_lcopy_value (const GValue *value,
static void static void
value_pointer_init (GValue *value) value_pointer_init (GValue *value)
{ {
value->data[0].v_pointer = 0; value->data[0].v_pointer = NULL;
} }
static void static void
@ -309,6 +309,76 @@ value_pointer_lcopy_value (const GValue *value,
return NULL; return NULL;
} }
static void
value_ccallback_init (GValue *value)
{
value->data[0].v_pointer = NULL;
value->data[1].v_pointer = NULL;
}
static void
value_ccallback_copy (const GValue *src_value,
GValue *dest_value)
{
dest_value->data[0].v_pointer = src_value->data[0].v_pointer;
dest_value->data[1].v_pointer = src_value->data[1].v_pointer;
}
static gchar*
value_ccallback_collect_value (GValue *value,
guint nth_value,
GType *collect_type,
GTypeCValue *collect_value)
{
gchar *error = NULL;
switch (nth_value)
{
case 0:
value->data[0].v_pointer = collect_value->v_pointer;
*collect_type = G_VALUE_COLLECT_POINTER;
if (!value->data[0].v_pointer)
error = g_strconcat ("invalid (NULL) pointer callback function for value type `",
G_VALUE_TYPE_NAME (value),
"'",
NULL);
break;
case 1:
value->data[1].v_pointer = collect_value->v_pointer;
*collect_type = 0;
break;
}
return error;
}
static gchar*
value_ccallback_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 ("%s location for `%s' passed as NULL",
nth_value ? "data" : "callback",
G_VALUE_TYPE_NAME (value));
switch (nth_value)
{
case 0:
*pointer_p = value->data[0].v_pointer;
*collect_type = G_VALUE_COLLECT_POINTER;
break;
case 1:
*pointer_p = value->data[1].v_pointer;
*collect_type = 0;
break;
}
return NULL;
}
/* --- type initialization --- */ /* --- type initialization --- */
void void
@ -478,6 +548,24 @@ g_value_types_init (void) /* sync with gtype.c */
type = g_type_register_fundamental (G_TYPE_POINTER, "gpointer", &info, &finfo, 0); type = g_type_register_fundamental (G_TYPE_POINTER, "gpointer", &info, &finfo, 0);
g_assert (type == G_TYPE_POINTER); g_assert (type == G_TYPE_POINTER);
} }
/* G_TYPE_CCALLBACK
*/
{
static const GTypeValueTable value_table = {
value_ccallback_init, /* value_init */
NULL, /* value_free */
value_ccallback_copy, /* value_copy */
NULL, /* value_peek_pointer */
G_VALUE_COLLECT_POINTER, /* collect_type */
value_ccallback_collect_value, /* collect_value */
G_VALUE_COLLECT_POINTER, /* lcopy_type */
value_ccallback_lcopy_value, /* lcopy_value */
};
info.value_table = &value_table;
type = g_type_register_fundamental (G_TYPE_CCALLBACK, "GCCallback", &info, &finfo, 0);
g_assert (type == G_TYPE_CCALLBACK);
}
} }
@ -692,3 +780,27 @@ g_value_get_pointer (const GValue *value)
return value->data[0].v_pointer; return value->data[0].v_pointer;
} }
void
g_value_set_ccallback (GValue *value,
gpointer callback_func,
gpointer callback_data)
{
g_return_if_fail (G_IS_VALUE_CCALLBACK (value));
value->data[0].v_pointer = callback_func;
value->data[1].v_pointer = callback_data;
}
void
g_value_get_ccallback (const GValue *value,
gpointer *callback_func,
gpointer *callback_data)
{
g_return_if_fail (G_IS_VALUE_CCALLBACK (value));
if (callback_func)
*callback_func = value->data[0].v_pointer;
if (callback_data)
*callback_data = value->data[1].v_pointer;
}

View File

@ -42,6 +42,7 @@ extern "C" {
#define G_IS_VALUE_DOUBLE(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_DOUBLE)) #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_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)) #define G_IS_VALUE_POINTER(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_POINTER))
#define G_IS_VALUE_CCALLBACK(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_CCALLBACK))
/* --- prototypes --- */ /* --- prototypes --- */
@ -81,7 +82,12 @@ gchar* g_value_dup_string (const GValue *value);
void g_value_set_pointer (GValue *value, void g_value_set_pointer (GValue *value,
gpointer v_pointer); gpointer v_pointer);
gpointer g_value_get_pointer (const GValue *value); gpointer g_value_get_pointer (const GValue *value);
void g_value_set_ccallback (GValue *value,
gpointer callback_func,
gpointer callback_data);
void g_value_get_ccallback (const GValue *value,
gpointer *callback_func,
gpointer *callback_data);

View File

@ -16,7 +16,7 @@ GLIB_VER = @GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@
# Nothing much configurable below # Nothing much configurable below
INCLUDES = -I .. -I . INCLUDES = -I .. -I .
DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gobject DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gruntime
BUILD_DLL = ../build-dll BUILD_DLL = ../build-dll

View File

@ -13,7 +13,7 @@ GLIB_VER = @GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@
# Nothing much configurable below # Nothing much configurable below
INCLUDES = -I .. -I . INCLUDES = -I .. -I .
DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gobject DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gruntime
all : \ all : \
gobject-$(GLIB_VER).dll \ gobject-$(GLIB_VER).dll \