Patch from David Benson <daveb@idealab.com> to add user_data support to

Mon Nov 20 18:55:17 2000  Jonathan Blandford  <jrb@redhat.com>

	* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
	user_data support to gtree functions.

Mon Nov 13 18:35:52 2000  Jonathan Blandford  <jrb@redhat.com>

	* gtypes.h (GCompareFuncData): new func type to let you use user
	data when comparing nodes.

	* gslist.c (g_list_sort_with_data): new function to sort with
	user_data.

	* glist.c (g_list_sort_with_data): new function to sort with
	user_data.

	* garray.[ch]: Added convenience functions to sort arrays.
This commit is contained in:
Jonathan Blandford 2000-11-20 23:59:32 +00:00 committed by Jonathan Blandford
parent 40d62d0dd7
commit 2645aaf59c
34 changed files with 1584 additions and 442 deletions

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -1,3 +1,21 @@
Mon Nov 20 18:55:17 2000 Jonathan Blandford <jrb@redhat.com>
* gtree.[hc]: Patch from David Benson <daveb@idealab.com> to add
user_data support to gtree functions.
Mon Nov 13 18:35:52 2000 Jonathan Blandford <jrb@redhat.com>
* gtypes.h (GCompareFuncData): new func type to let you use user
data when comparing nodes.
* gslist.c (g_list_sort_with_data): new function to sort with
user_data.
* glist.c (g_list_sort_with_data): new function to sort with
user_data.
* garray.[ch]: Added convenience functions to sort arrays.
2000-11-16 Havoc Pennington <hp@redhat.com>
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps

View File

@ -66,6 +66,7 @@ libglib_1_3_la_SOURCES = \
gmessages.c \
gnode.c \
gprimes.c \
gqsort.c \
gqueue.c \
grel.c \
grand.c \
@ -115,6 +116,7 @@ glibinclude_HEADERS = \
gmessages.h \
gnode.h \
gprimes.h \
gqsort.h \
gquark.h \
gqueue.h \
grand.h \

View File

@ -29,6 +29,7 @@
*/
#include <string.h>
#include <stdlib.h>
#include "glib.h"
@ -264,6 +265,39 @@ g_array_remove_index_fast (GArray* farray,
return farray;
}
void
g_array_sort (GArray *farray,
GCompareFunc compare_func)
{
GRealArray *array = (GRealArray*) farray;
g_return_if_fail (array != NULL);
g_return_if_fail (array->data != NULL);
qsort (array->data,
array->len,
array->elt_size,
compare_func);
}
void
g_array_sort_with_data (GArray *farray,
GCompareFuncData compare_func,
gpointer user_data)
{
GRealArray *array = (GRealArray*) farray;
g_return_if_fail (array != NULL);
g_return_if_fail (array->data != NULL);
g_qsort_with_data (array->data,
array->len,
array->elt_size,
compare_func,
user_data);
}
static gint
g_nearest_pow (gint num)
{
@ -527,6 +561,34 @@ g_ptr_array_add (GPtrArray* farray,
array->pdata[array->len++] = data;
}
void
g_ptr_array_sort (GPtrArray *array,
GCompareFunc compare_func)
{
g_return_if_fail (array != NULL);
g_return_if_fail (array->pdata != NULL);
qsort (array->pdata,
array->len,
sizeof (gpointer),
compare_func);
}
void
g_ptr_array_sort_with_data (GPtrArray *array,
GCompareFuncData compare_func,
gpointer user_data)
{
g_return_if_fail (array != NULL);
g_return_if_fail (array->pdata != NULL);
g_qsort_with_data (array->pdata,
array->len,
sizeof (gpointer),
compare_func,
user_data);
}
/* Byte arrays
*/
@ -581,9 +643,24 @@ GByteArray* g_byte_array_remove_index (GByteArray *array,
}
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
guint index)
guint index)
{
g_array_remove_index_fast((GArray*) array, index);
return array;
}
void
g_byte_array_sort (GByteArray *array,
GCompareFunc compare_func)
{
g_array_sort ((GArray *) array, compare_func);
}
void
g_byte_array_sort_with_data (GByteArray *array,
GCompareFuncData compare_func,
gpointer user_data)
{
g_array_sort_with_data ((GArray *) array, compare_func, user_data);
}

133
garray.h
View File

@ -63,75 +63,92 @@ struct _GPtrArray
#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &v, 1)
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
GArray* g_array_new (gboolean zero_terminated,
gboolean clear,
guint element_size);
GArray* g_array_sized_new (gboolean zero_terminated,
gboolean clear,
guint element_size,
guint reserved_size);
gchar* g_array_free (GArray *array,
gboolean free_segment);
GArray* g_array_append_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_prepend_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_insert_vals (GArray *array,
guint index,
gconstpointer data,
guint len);
GArray* g_array_set_size (GArray *array,
guint length);
GArray* g_array_remove_index (GArray *array,
guint index);
GArray* g_array_remove_index_fast (GArray *array,
guint index);
GArray* g_array_new (gboolean zero_terminated,
gboolean clear,
guint element_size);
GArray* g_array_sized_new (gboolean zero_terminated,
gboolean clear,
guint element_size,
guint reserved_size);
gchar* g_array_free (GArray *array,
gboolean free_segment);
GArray* g_array_append_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_prepend_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_insert_vals (GArray *array,
guint index,
gconstpointer data,
guint len);
GArray* g_array_set_size (GArray *array,
guint length);
GArray* g_array_remove_index (GArray *array,
guint index);
GArray* g_array_remove_index_fast (GArray *array,
guint index);
void g_array_sort (GArray *array,
GCompareFunc compare_func);
void g_array_sort_with_data (GArray *array,
GCompareFuncData compare_func,
gpointer user_data);
/* Resizable pointer array. This interface is much less complicated
* than the above. Add appends appends a pointer. Remove fills any
* cleared spot and shortens the array. remove_fast will again distort
* order.
*/
#define g_ptr_array_index(array,index) (array->pdata)[index]
GPtrArray* g_ptr_array_new (void);
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
gpointer* g_ptr_array_free (GPtrArray *array,
gboolean free_seg);
void g_ptr_array_set_size (GPtrArray *array,
gint length);
gpointer g_ptr_array_remove_index (GPtrArray *array,
guint index);
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
guint index);
gboolean g_ptr_array_remove (GPtrArray *array,
gpointer data);
gboolean g_ptr_array_remove_fast (GPtrArray *array,
gpointer data);
void g_ptr_array_add (GPtrArray *array,
gpointer data);
#define g_ptr_array_index(array,index) (array->pdata)[index]
GPtrArray* g_ptr_array_new (void);
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
gpointer* g_ptr_array_free (GPtrArray *array,
gboolean free_seg);
void g_ptr_array_set_size (GPtrArray *array,
gint length);
gpointer g_ptr_array_remove_index (GPtrArray *array,
guint index);
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
guint index);
gboolean g_ptr_array_remove (GPtrArray *array,
gpointer data);
gboolean g_ptr_array_remove_fast (GPtrArray *array,
gpointer data);
void g_ptr_array_add (GPtrArray *array,
gpointer data);
void g_ptr_array_sort (GPtrArray *array,
GCompareFunc compare_func);
void g_ptr_array_sort_with_data (GPtrArray *array,
GCompareFuncData compare_func,
gpointer user_data);
/* Byte arrays, an array of guint8. Implemented as a GArray,
* but type-safe.
*/
GByteArray* g_byte_array_new (void);
GByteArray* g_byte_array_sized_new (guint reserved_size);
guint8* g_byte_array_free (GByteArray *array,
gboolean free_segment);
GByteArray* g_byte_array_append (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_prepend (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_set_size (GByteArray *array,
guint length);
GByteArray* g_byte_array_remove_index (GByteArray *array,
guint index);
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
guint index);
GByteArray* g_byte_array_new (void);
GByteArray* g_byte_array_sized_new (guint reserved_size);
guint8* g_byte_array_free (GByteArray *array,
gboolean free_segment);
GByteArray* g_byte_array_append (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_prepend (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_set_size (GByteArray *array,
guint length);
GByteArray* g_byte_array_remove_index (GByteArray *array,
guint index);
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
guint index);
void g_byte_array_sort (GByteArray *array,
GCompareFunc compare_func);
void g_byte_array_sort_with_data (GByteArray *array,
GCompareFuncData compare_func,
gpointer user_data);
G_END_DECLS

1
glib.h
View File

@ -49,6 +49,7 @@
#include <gmessages.h>
#include <gnode.h>
#include <gprimes.h>
#include <gqsort.h>
#include <gquark.h>
#include <gqueue.h>
#include <grand.h>

View File

@ -66,6 +66,7 @@ libglib_1_3_la_SOURCES = \
gmessages.c \
gnode.c \
gprimes.c \
gqsort.c \
gqueue.c \
grel.c \
grand.c \
@ -115,6 +116,7 @@ glibinclude_HEADERS = \
gmessages.h \
gnode.h \
gprimes.h \
gqsort.h \
gquark.h \
gqueue.h \
grand.h \

View File

@ -29,6 +29,7 @@
*/
#include <string.h>
#include <stdlib.h>
#include "glib.h"
@ -264,6 +265,39 @@ g_array_remove_index_fast (GArray* farray,
return farray;
}
void
g_array_sort (GArray *farray,
GCompareFunc compare_func)
{
GRealArray *array = (GRealArray*) farray;
g_return_if_fail (array != NULL);
g_return_if_fail (array->data != NULL);
qsort (array->data,
array->len,
array->elt_size,
compare_func);
}
void
g_array_sort_with_data (GArray *farray,
GCompareFuncData compare_func,
gpointer user_data)
{
GRealArray *array = (GRealArray*) farray;
g_return_if_fail (array != NULL);
g_return_if_fail (array->data != NULL);
g_qsort_with_data (array->data,
array->len,
array->elt_size,
compare_func,
user_data);
}
static gint
g_nearest_pow (gint num)
{
@ -527,6 +561,34 @@ g_ptr_array_add (GPtrArray* farray,
array->pdata[array->len++] = data;
}
void
g_ptr_array_sort (GPtrArray *array,
GCompareFunc compare_func)
{
g_return_if_fail (array != NULL);
g_return_if_fail (array->pdata != NULL);
qsort (array->pdata,
array->len,
sizeof (gpointer),
compare_func);
}
void
g_ptr_array_sort_with_data (GPtrArray *array,
GCompareFuncData compare_func,
gpointer user_data)
{
g_return_if_fail (array != NULL);
g_return_if_fail (array->pdata != NULL);
g_qsort_with_data (array->pdata,
array->len,
sizeof (gpointer),
compare_func,
user_data);
}
/* Byte arrays
*/
@ -581,9 +643,24 @@ GByteArray* g_byte_array_remove_index (GByteArray *array,
}
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
guint index)
guint index)
{
g_array_remove_index_fast((GArray*) array, index);
return array;
}
void
g_byte_array_sort (GByteArray *array,
GCompareFunc compare_func)
{
g_array_sort ((GArray *) array, compare_func);
}
void
g_byte_array_sort_with_data (GByteArray *array,
GCompareFuncData compare_func,
gpointer user_data)
{
g_array_sort_with_data ((GArray *) array, compare_func, user_data);
}

View File

@ -63,75 +63,92 @@ struct _GPtrArray
#define g_array_insert_val(a,i,v) g_array_insert_vals (a, i, &v, 1)
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
GArray* g_array_new (gboolean zero_terminated,
gboolean clear,
guint element_size);
GArray* g_array_sized_new (gboolean zero_terminated,
gboolean clear,
guint element_size,
guint reserved_size);
gchar* g_array_free (GArray *array,
gboolean free_segment);
GArray* g_array_append_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_prepend_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_insert_vals (GArray *array,
guint index,
gconstpointer data,
guint len);
GArray* g_array_set_size (GArray *array,
guint length);
GArray* g_array_remove_index (GArray *array,
guint index);
GArray* g_array_remove_index_fast (GArray *array,
guint index);
GArray* g_array_new (gboolean zero_terminated,
gboolean clear,
guint element_size);
GArray* g_array_sized_new (gboolean zero_terminated,
gboolean clear,
guint element_size,
guint reserved_size);
gchar* g_array_free (GArray *array,
gboolean free_segment);
GArray* g_array_append_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_prepend_vals (GArray *array,
gconstpointer data,
guint len);
GArray* g_array_insert_vals (GArray *array,
guint index,
gconstpointer data,
guint len);
GArray* g_array_set_size (GArray *array,
guint length);
GArray* g_array_remove_index (GArray *array,
guint index);
GArray* g_array_remove_index_fast (GArray *array,
guint index);
void g_array_sort (GArray *array,
GCompareFunc compare_func);
void g_array_sort_with_data (GArray *array,
GCompareFuncData compare_func,
gpointer user_data);
/* Resizable pointer array. This interface is much less complicated
* than the above. Add appends appends a pointer. Remove fills any
* cleared spot and shortens the array. remove_fast will again distort
* order.
*/
#define g_ptr_array_index(array,index) (array->pdata)[index]
GPtrArray* g_ptr_array_new (void);
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
gpointer* g_ptr_array_free (GPtrArray *array,
gboolean free_seg);
void g_ptr_array_set_size (GPtrArray *array,
gint length);
gpointer g_ptr_array_remove_index (GPtrArray *array,
guint index);
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
guint index);
gboolean g_ptr_array_remove (GPtrArray *array,
gpointer data);
gboolean g_ptr_array_remove_fast (GPtrArray *array,
gpointer data);
void g_ptr_array_add (GPtrArray *array,
gpointer data);
#define g_ptr_array_index(array,index) (array->pdata)[index]
GPtrArray* g_ptr_array_new (void);
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
gpointer* g_ptr_array_free (GPtrArray *array,
gboolean free_seg);
void g_ptr_array_set_size (GPtrArray *array,
gint length);
gpointer g_ptr_array_remove_index (GPtrArray *array,
guint index);
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
guint index);
gboolean g_ptr_array_remove (GPtrArray *array,
gpointer data);
gboolean g_ptr_array_remove_fast (GPtrArray *array,
gpointer data);
void g_ptr_array_add (GPtrArray *array,
gpointer data);
void g_ptr_array_sort (GPtrArray *array,
GCompareFunc compare_func);
void g_ptr_array_sort_with_data (GPtrArray *array,
GCompareFuncData compare_func,
gpointer user_data);
/* Byte arrays, an array of guint8. Implemented as a GArray,
* but type-safe.
*/
GByteArray* g_byte_array_new (void);
GByteArray* g_byte_array_sized_new (guint reserved_size);
guint8* g_byte_array_free (GByteArray *array,
gboolean free_segment);
GByteArray* g_byte_array_append (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_prepend (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_set_size (GByteArray *array,
guint length);
GByteArray* g_byte_array_remove_index (GByteArray *array,
guint index);
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
guint index);
GByteArray* g_byte_array_new (void);
GByteArray* g_byte_array_sized_new (guint reserved_size);
guint8* g_byte_array_free (GByteArray *array,
gboolean free_segment);
GByteArray* g_byte_array_append (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_prepend (GByteArray *array,
const guint8 *data,
guint len);
GByteArray* g_byte_array_set_size (GByteArray *array,
guint length);
GByteArray* g_byte_array_remove_index (GByteArray *array,
guint index);
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
guint index);
void g_byte_array_sort (GByteArray *array,
GCompareFunc compare_func);
void g_byte_array_sort_with_data (GByteArray *array,
GCompareFuncData compare_func,
gpointer user_data);
G_END_DECLS

View File

@ -49,6 +49,7 @@
#include <gmessages.h>
#include <gnode.h>
#include <gprimes.h>
#include <gqsort.h>
#include <gquark.h>
#include <gqueue.h>
#include <grand.h>

View File

@ -596,18 +596,26 @@ g_list_insert_sorted (GList *list,
}
static GList *
g_list_sort_merge (GList *l1,
GList *l2,
GCompareFunc compare_func)
g_list_sort_merge (GList *l1,
GList *l2,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GList list, *l, *lprev;
gint cmp;
l = &list;
lprev = NULL;
while (l1 && l2)
{
if (compare_func (l1->data, l2->data) < 0)
if (use_data)
cmp = ((GCompareFuncData) compare_func) (l1->data, l2->data, user_data);
else
cmp = ((GCompareFunc) compare_func) (l1->data, l2->data);
if (cmp <= 0)
{
l->next = l1;
l = l->next;
@ -631,8 +639,10 @@ g_list_sort_merge (GList *l1,
}
GList*
g_list_sort (GList *list,
GCompareFunc compare_func)
g_list_sort_real (GList *list,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GList *l1, *l2;
@ -653,9 +663,27 @@ g_list_sort (GList *list,
l2 = l1->next;
l1->next = NULL;
return g_list_sort_merge (g_list_sort (list, compare_func),
g_list_sort (l2, compare_func),
compare_func);
return g_list_sort_merge (g_list_sort_real (list, compare_func, use_data, user_data),
g_list_sort_real (l2, compare_func, use_data, user_data),
compare_func,
use_data,
user_data);
}
GList *
g_list_sort (GList *list,
GCompareFunc compare_func)
{
return g_list_sort_real (list, (GFunc) compare_func, FALSE, NULL);
}
GList *
g_list_sort_with_data (GList *list,
GCompareFuncData compare_func,
gpointer user_data)
{
return g_list_sort_real (list, (GFunc) compare_func, TRUE, user_data);
}
GList*
@ -691,7 +719,8 @@ g_list_sort2 (GList *list,
{
dst->data = g_list_sort_merge (src->data,
src->next->data,
compare_func);
(GFunc) compare_func,
FALSE, NULL);
dstprev = dst;
dst = dst->next;
src = src->next->next;

View File

@ -42,52 +42,56 @@ struct _GList
/* Doubly linked lists
*/
void g_list_push_allocator (GAllocator *allocator);
void g_list_pop_allocator (void);
GList* g_list_alloc (void);
void g_list_free (GList *list);
void g_list_free_1 (GList *list);
GList* g_list_append (GList *list,
gpointer data);
GList* g_list_prepend (GList *list,
gpointer data);
GList* g_list_insert (GList *list,
gpointer data,
gint position);
GList* g_list_insert_sorted (GList *list,
gpointer data,
GCompareFunc func);
GList* g_list_concat (GList *list1,
GList *list2);
GList* g_list_remove (GList *list,
gconstpointer data);
GList* g_list_remove_link (GList *list,
GList *llink);
GList* g_list_delete_link (GList *list,
GList *link);
GList* g_list_reverse (GList *list);
GList* g_list_copy (GList *list);
GList* g_list_nth (GList *list,
guint n);
GList* g_list_find (GList *list,
gconstpointer data);
GList* g_list_find_custom (GList *list,
gconstpointer data,
GCompareFunc func);
gint g_list_position (GList *list,
GList *llink);
gint g_list_index (GList *list,
gconstpointer data);
GList* g_list_last (GList *list);
GList* g_list_first (GList *list);
guint g_list_length (GList *list);
void g_list_foreach (GList *list,
GFunc func,
gpointer user_data);
GList* g_list_sort (GList *list,
GCompareFunc compare_func);
gpointer g_list_nth_data (GList *list,
guint n);
void g_list_push_allocator (GAllocator *allocator);
void g_list_pop_allocator (void);
GList* g_list_alloc (void);
void g_list_free (GList *list);
void g_list_free_1 (GList *list);
GList* g_list_append (GList *list,
gpointer data);
GList* g_list_prepend (GList *list,
gpointer data);
GList* g_list_insert (GList *list,
gpointer data,
gint position);
GList* g_list_insert_sorted (GList *list,
gpointer data,
GCompareFunc func);
GList* g_list_concat (GList *list1,
GList *list2);
GList* g_list_remove (GList *list,
gconstpointer data);
GList* g_list_remove_link (GList *list,
GList *llink);
GList* g_list_delete_link (GList *list,
GList *link);
GList* g_list_reverse (GList *list);
GList* g_list_copy (GList *list);
GList* g_list_nth (GList *list,
guint n);
GList* g_list_find (GList *list,
gconstpointer data);
GList* g_list_find_custom (GList *list,
gconstpointer data,
GCompareFunc func);
gint g_list_position (GList *list,
GList *llink);
gint g_list_index (GList *list,
gconstpointer data);
GList* g_list_last (GList *list);
GList* g_list_first (GList *list);
guint g_list_length (GList *list);
void g_list_foreach (GList *list,
GFunc func,
gpointer user_data);
GList* g_list_sort (GList *list,
GCompareFunc compare_func);
GList* g_list_sort_with_data (GList *list,
GCompareFuncData compare_func,
gpointer user_data);
gpointer g_list_nth_data (GList *list,
guint n);
#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)

269
glib/gqsort.c Normal file
View File

@ -0,0 +1,269 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
* Copyright (C) 2000 Eazel, Inc.
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* This file was originally part of the GNU C Library, and was modified to allow
* user data to be passed in to the sorting function.
*
* Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
* Modified by Maciej Stachowiak (mjs@eazel.com)
*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/. */
#include <string.h>
#include "glib.h"
/* Byte-wise swap two items of size SIZE. */
#define SWAP(a, b, size) \
do \
{ \
register size_t __size = (size); \
register char *__a = (a), *__b = (b); \
do \
{ \
char __tmp = *__a; \
*__a++ = *__b; \
*__b++ = __tmp; \
} while (--__size > 0); \
} while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 4
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct
{
char *lo;
char *hi;
}
stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (8 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
/* Order size using quicksort. This implementation incorporates
* four optimizations discussed in Sedgewick:
*
* 1. Non-recursive, using an explicit stack of pointer that store the next
* array partition to sort. To save time, this maximum amount of space
* required to store an array of MAX_INT is allocated on the stack. Assuming
* a 32-bit integer, this needs only 32 * sizeof(stack_node) == 136 bits.
* Pretty cheap, actually.
*
* 2. Chose the pivot element using a median-of-three decision tree. This
* reduces the probability of selecting a bad pivot value and eliminates
* certain * extraneous comparisons.
*
* 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion
* sort to order the MAX_THRESH items within each partition. This is a big
* win, since insertion sort is faster for small, mostly sorted array
* segments.
*
* 4. The larger of the two sub-partitions is always pushed onto the stack
* first, with the algorithm then concentrating on the smaller partition.
* This *guarantees* no more than log (n) stack size is needed (actually O(1)
* in this case)!
*/
void
g_qsort_with_data (gconstpointer pbase,
gint total_elems,
size_t size,
GCompareFuncData compare_func,
gpointer user_data)
{
register char *base_ptr = (char *) pbase;
/* Allocating SIZE bytes for a pivot buffer facilitates a better
* algorithm below since we can do comparisons directly on the pivot.
*/
char *pivot_buffer = (char *) alloca (size);
const size_t max_thresh = MAX_THRESH * size;
g_return_if_fail (total_elems > 0);
g_return_if_fail (pbase != NULL);
g_return_if_fail (compare_func != NULL);
if (total_elems > MAX_THRESH)
{
char *lo = base_ptr;
char *hi = &lo[size * (total_elems - 1)];
/* Largest size needed for 32-bit int!!! */
stack_node stack[STACK_SIZE];
stack_node *top = stack + 1;
while (STACK_NOT_EMPTY)
{
char *left_ptr;
char *right_ptr;
char *pivot = pivot_buffer;
/* Select median value from among LO, MID, and HI. Rearrange
* LO and HI so the three values are sorted. This lowers the
* probability of picking a pathological pivot value and
* skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
char *mid = lo + size * ((hi - lo) / size >> 1);
if ((*compare_func) ((void *) mid, (void *) lo, user_data) < 0)
SWAP (mid, lo, size);
if ((*compare_func) ((void *) hi, (void *) mid, user_data) < 0)
SWAP (mid, hi, size);
else
goto jump_over;
if ((*compare_func) ((void *) mid, (void *) lo, user_data) < 0)
SWAP (mid, lo, size);
jump_over:;
memcpy (pivot, mid, size);
pivot = pivot_buffer;
left_ptr = lo + size;
right_ptr = hi - size;
/* Here's the famous ``collapse the walls'' section of quicksort.
* Gotta like those tight inner loops! They are the main reason
* that this algorithm runs much faster than others. */
do
{
while ((*compare_func)
((void *) left_ptr, (void *) pivot,
user_data) < 0)
left_ptr += size;
while ((*compare_func)
((void *) pivot, (void *) right_ptr,
user_data) < 0)
right_ptr -= size;
if (left_ptr < right_ptr)
{
SWAP (left_ptr, right_ptr, size);
left_ptr += size;
right_ptr -= size;
}
else if (left_ptr == right_ptr)
{
left_ptr += size;
right_ptr -= size;
break;
}
}
while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
* left and right partitions are below the threshold size. If so,
* ignore one or both. Otherwise, push the larger partition's
* bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= max_thresh)
{
if ((size_t) (hi - left_ptr) <= max_thresh)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= max_thresh)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr))
{
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else
{
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
* is completely sorted using insertion sort, since this is efficient
* for partitions below MAX_THRESH size. BASE_PTR points to the beginning
* of the array to sort, and END_PTR points at the very last element in
* the array (*not* one beyond it!). */
{
char *const end_ptr = &base_ptr[size * (total_elems - 1)];
char *tmp_ptr = base_ptr;
char *thresh = MIN (end_ptr, base_ptr + max_thresh);
register char *run_ptr;
/* Find smallest element in first threshold and place it at the
* array's beginning. This is the smallest array element,
* and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + size; run_ptr <= thresh;
run_ptr +=
size) if ((*compare_func) ((void *) run_ptr, (void *) tmp_ptr,
user_data) < 0)
tmp_ptr = run_ptr;
if (tmp_ptr != base_ptr)
SWAP (tmp_ptr, base_ptr, size);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = base_ptr + size;
while ((run_ptr += size) <= end_ptr)
{
tmp_ptr = run_ptr - size;
while ((*compare_func)
((void *) run_ptr, (void *) tmp_ptr,
user_data) < 0)
tmp_ptr -= size;
tmp_ptr += size;
if (tmp_ptr != run_ptr)
{
char *trav;
trav = run_ptr + size;
while (--trav >= run_ptr)
{
char c = *trav;
char *hi, *lo;
for (hi = lo = trav;
(lo -= size) >= tmp_ptr; hi = lo)
*hi = *lo;
*hi = c;
}
}
}
}
}

44
glib/gqsort.h Normal file
View File

@ -0,0 +1,44 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_QSORT_H__
#define __G_QSORT_H__
#include <gtypes.h>
G_BEGIN_DECLS
void g_qsort_with_data (gconstpointer pbase,
gint total_elems,
size_t size,
GCompareFuncData compare_func,
gpointer user_data);
G_END_DECLS
#endif /* __G_QSORT_H__ */

View File

@ -580,18 +580,26 @@ g_slist_insert_sorted (GSList *list,
}
}
static GSList*
g_slist_sort_merge (GSList *l1,
GSList *l2,
GCompareFunc compare_func)
static GSList *
g_slist_sort_merge (GSList *l1,
GSList *l2,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GSList list, *l;
gint cmp;
l=&list;
while (l1 && l2)
{
if (compare_func(l1->data,l2->data) < 0)
if (use_data)
cmp = ((GCompareFuncData) compare_func) (l1->data, l2->data, user_data);
else
cmp = ((GCompareFunc) compare_func) (l1->data, l2->data);
if (cmp <= 0)
{
l=l->next=l1;
l1=l1->next;
@ -607,9 +615,11 @@ g_slist_sort_merge (GSList *l1,
return list.next;
}
GSList*
g_slist_sort (GSList *list,
GCompareFunc compare_func)
static GSList *
g_slist_sort_real (GSList *list,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GSList *l1, *l2;
@ -630,7 +640,24 @@ g_slist_sort (GSList *list,
l2 = l1->next;
l1->next = NULL;
return g_slist_sort_merge (g_slist_sort (list, compare_func),
g_slist_sort (l2, compare_func),
compare_func);
return g_slist_sort_merge (g_slist_sort_real (list, compare_func, use_data, user_data),
g_slist_sort_real (l2, compare_func, use_data, user_data),
compare_func,
use_data,
user_data);
}
GSList *
g_slist_sort (GSList *list,
GCompareFunc compare_func)
{
return g_slist_sort_real (list, (GFunc) compare_func, FALSE, NULL);
}
GSList *
g_slist_sort_with_data (GSList *list,
GCompareFuncData compare_func,
gpointer user_data)
{
return g_slist_sort_real (list, (GFunc) compare_func, TRUE, user_data);
}

View File

@ -41,54 +41,57 @@ struct _GSList
/* Singly linked lists
*/
void g_slist_push_allocator (GAllocator *allocator);
void g_slist_pop_allocator (void);
GSList* g_slist_alloc (void);
void g_slist_free (GSList *list);
void g_slist_free_1 (GSList *list);
GSList* g_slist_append (GSList *list,
gpointer data);
GSList* g_slist_prepend (GSList *list,
gpointer data);
GSList* g_slist_insert (GSList *list,
gpointer data,
gint position);
GSList* g_slist_insert_sorted (GSList *list,
gpointer data,
GCompareFunc func);
GSList* g_slist_insert_before (GSList *slist,
GSList *sibling,
gpointer data);
GSList* g_slist_concat (GSList *list1,
GSList *list2);
GSList* g_slist_remove (GSList *list,
gconstpointer data);
GSList* g_slist_remove_link (GSList *list,
GSList *link);
GSList* g_slist_delete_link (GSList *list,
GSList *link);
GSList* g_slist_reverse (GSList *list);
GSList* g_slist_copy (GSList *list);
GSList* g_slist_nth (GSList *list,
guint n);
GSList* g_slist_find (GSList *list,
gconstpointer data);
GSList* g_slist_find_custom (GSList *list,
gconstpointer data,
GCompareFunc func);
gint g_slist_position (GSList *list,
GSList *llink);
gint g_slist_index (GSList *list,
gconstpointer data);
GSList* g_slist_last (GSList *list);
guint g_slist_length (GSList *list);
void g_slist_foreach (GSList *list,
GFunc func,
gpointer user_data);
GSList* g_slist_sort (GSList *list,
GCompareFunc compare_func);
gpointer g_slist_nth_data (GSList *list,
guint n);
void g_slist_push_allocator (GAllocator *allocator);
void g_slist_pop_allocator (void);
GSList* g_slist_alloc (void);
void g_slist_free (GSList *list);
void g_slist_free_1 (GSList *list);
GSList* g_slist_append (GSList *list,
gpointer data);
GSList* g_slist_prepend (GSList *list,
gpointer data);
GSList* g_slist_insert (GSList *list,
gpointer data,
gint position);
GSList* g_slist_insert_sorted (GSList *list,
gpointer data,
GCompareFunc func);
GSList* g_slist_insert_before (GSList *slist,
GSList *sibling,
gpointer data);
GSList* g_slist_concat (GSList *list1,
GSList *list2);
GSList* g_slist_remove (GSList *list,
gconstpointer data);
GSList* g_slist_remove_link (GSList *list,
GSList *link);
GSList* g_slist_delete_link (GSList *list,
GSList *link);
GSList* g_slist_reverse (GSList *list);
GSList* g_slist_copy (GSList *list);
GSList* g_slist_nth (GSList *list,
guint n);
GSList* g_slist_find (GSList *list,
gconstpointer data);
GSList* g_slist_find_custom (GSList *list,
gconstpointer data,
GCompareFunc func);
gint g_slist_position (GSList *list,
GSList *llink);
gint g_slist_index (GSList *list,
gconstpointer data);
GSList* g_slist_last (GSList *list);
guint g_slist_length (GSList *list);
void g_slist_foreach (GSList *list,
GFunc func,
gpointer user_data);
GSList* g_slist_sort (GSList *list,
GCompareFunc compare_func);
GSList* g_slist_sort_with_data (GSList *list,
GCompareFuncData compare_func,
gpointer user_data);
gpointer g_slist_nth_data (GSList *list,
guint n);
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
G_END_DECLS

View File

@ -37,7 +37,8 @@ typedef struct _GTreeNode GTreeNode;
struct _GRealTree
{
GTreeNode *root;
GCompareFunc key_compare;
GCompareFuncData key_compare;
gpointer key_compare_data;
};
struct _GTreeNode
@ -54,12 +55,14 @@ static GTreeNode* g_tree_node_new (gpointer key,
gpointer value);
static void g_tree_node_destroy (GTreeNode *node);
static GTreeNode* g_tree_node_insert (GTreeNode *node,
GCompareFunc compare,
GCompareFuncData compare,
gpointer comp_data,
gpointer key,
gpointer value,
gint *inserted);
static GTreeNode* g_tree_node_remove (GTreeNode *node,
GCompareFunc compare,
GCompareFuncData compare,
gpointer comp_data,
gconstpointer key);
static GTreeNode* g_tree_node_balance (GTreeNode *node);
static GTreeNode* g_tree_node_remove_leftmost (GTreeNode *node,
@ -69,7 +72,8 @@ static GTreeNode* g_tree_node_restore_left_balance (GTreeNode *node,
static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
gint old_balance);
static gpointer g_tree_node_lookup (GTreeNode *node,
GCompareFunc compare,
GCompareFuncData compare,
gpointer comp_data,
gconstpointer key);
static gint g_tree_node_count (GTreeNode *node);
static gint g_tree_node_pre_order (GTreeNode *node,
@ -149,9 +153,8 @@ g_tree_node_destroy (GTreeNode *node)
}
}
GTree*
g_tree_new (GCompareFunc key_compare_func)
GTree* g_tree_new_udata(GCompareFuncData key_compare_func,
gpointer key_compare_data)
{
GRealTree *rtree;
@ -160,10 +163,18 @@ g_tree_new (GCompareFunc key_compare_func)
rtree = g_new (GRealTree, 1);
rtree->root = NULL;
rtree->key_compare = key_compare_func;
rtree->key_compare_data = key_compare_data;
return (GTree*) rtree;
}
GTree*
g_tree_new (GCompareFunc key_compare_func)
{
return g_tree_new_udata ((GCompareFuncData) key_compare_func, NULL);
}
void
g_tree_destroy (GTree *tree)
{
@ -191,6 +202,7 @@ g_tree_insert (GTree *tree,
inserted = FALSE;
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
rtree->key_compare_data,
key, value, &inserted);
}
@ -204,7 +216,8 @@ g_tree_remove (GTree *tree,
rtree = (GRealTree*) tree;
rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare, key);
rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare,
rtree->key_compare_data, key);
}
gpointer
@ -217,7 +230,8 @@ g_tree_lookup (GTree *tree,
rtree = (GRealTree*) tree;
return g_tree_node_lookup (rtree->root, rtree->key_compare, key);
return g_tree_node_lookup (rtree->root, rtree->key_compare,
rtree->key_compare_data, key);
}
void
@ -303,11 +317,12 @@ g_tree_nnodes (GTree *tree)
}
static GTreeNode*
g_tree_node_insert (GTreeNode *node,
GCompareFunc compare,
gpointer key,
gpointer value,
gint *inserted)
g_tree_node_insert (GTreeNode *node,
GCompareFuncData compare,
gpointer compare_data,
gpointer key,
gpointer value,
gint *inserted)
{
gint old_balance;
gint cmp;
@ -318,7 +333,7 @@ g_tree_node_insert (GTreeNode *node,
return g_tree_node_new (key, value);
}
cmp = (* compare) (key, node->key);
cmp = (* compare) (key, node->key, compare_data);
if (cmp == 0)
{
*inserted = FALSE;
@ -331,7 +346,8 @@ g_tree_node_insert (GTreeNode *node,
if (node->left)
{
old_balance = node->left->balance;
node->left = g_tree_node_insert (node->left, compare, key, value, inserted);
node->left = g_tree_node_insert (node->left, compare, compare_data,
key, value, inserted);
if ((old_balance != node->left->balance) && node->left->balance)
node->balance -= 1;
@ -348,7 +364,8 @@ g_tree_node_insert (GTreeNode *node,
if (node->right)
{
old_balance = node->right->balance;
node->right = g_tree_node_insert (node->right, compare, key, value, inserted);
node->right = g_tree_node_insert (node->right, compare, compare_data,
key, value, inserted);
if ((old_balance != node->right->balance) && node->right->balance)
node->balance += 1;
@ -371,9 +388,10 @@ g_tree_node_insert (GTreeNode *node,
}
static GTreeNode*
g_tree_node_remove (GTreeNode *node,
GCompareFunc compare,
gconstpointer key)
g_tree_node_remove (GTreeNode *node,
GCompareFuncData compare,
gpointer compare_data,
gconstpointer key)
{
GTreeNode *new_root;
gint old_balance;
@ -382,7 +400,7 @@ g_tree_node_remove (GTreeNode *node,
if (!node)
return NULL;
cmp = (* compare) (key, node->key);
cmp = (* compare) (key, node->key, compare_data);
if (cmp == 0)
{
GTreeNode *garbage;
@ -419,7 +437,7 @@ g_tree_node_remove (GTreeNode *node,
if (node->left)
{
old_balance = node->left->balance;
node->left = g_tree_node_remove (node->left, compare, key);
node->left = g_tree_node_remove (node->left, compare, compare_data, key);
node = g_tree_node_restore_left_balance (node, old_balance);
}
}
@ -428,7 +446,7 @@ g_tree_node_remove (GTreeNode *node,
if (node->right)
{
old_balance = node->right->balance;
node->right = g_tree_node_remove (node->right, compare, key);
node->right = g_tree_node_remove (node->right, compare, compare_data, key);
node = g_tree_node_restore_right_balance (node, old_balance);
}
}
@ -503,28 +521,29 @@ g_tree_node_restore_right_balance (GTreeNode *node,
}
static gpointer
g_tree_node_lookup (GTreeNode *node,
GCompareFunc compare,
gconstpointer key)
g_tree_node_lookup (GTreeNode *node,
GCompareFuncData compare,
gpointer compare_data,
gconstpointer key)
{
gint cmp;
if (!node)
return NULL;
cmp = (* compare) (key, node->key);
cmp = (* compare) (key, node->key, compare_data);
if (cmp == 0)
return node->value;
if (cmp < 0)
{
if (node->left)
return g_tree_node_lookup (node->left, compare, key);
return g_tree_node_lookup (node->left, compare, compare_data, key);
}
else if (cmp > 0)
{
if (node->right)
return g_tree_node_lookup (node->right, compare, key);
return g_tree_node_lookup (node->right, compare, compare_data, key);
}
return NULL;

View File

@ -39,24 +39,28 @@ typedef gint (*GTraverseFunc) (gpointer key,
/* Balanced binary trees
*/
GTree* g_tree_new (GCompareFunc key_compare_func);
void g_tree_destroy (GTree *tree);
void g_tree_insert (GTree *tree,
gpointer key,
gpointer value);
void g_tree_remove (GTree *tree,
gconstpointer key);
gpointer g_tree_lookup (GTree *tree,
gconstpointer key);
void g_tree_traverse (GTree *tree,
GTraverseFunc traverse_func,
GTraverseType traverse_type,
gpointer data);
gpointer g_tree_search (GTree *tree,
GCompareFunc search_func,
gconstpointer data);
gint g_tree_height (GTree *tree);
gint g_tree_nnodes (GTree *tree);
GTree* g_tree_new (GCompareFunc key_compare_func);
GTree* g_tree_new_with_data (GCompareFuncData key_compare_func,
gpointer user_data);
void g_tree_destroy (GTree *tree);
void g_tree_insert (GTree *tree,
gpointer key,
gpointer value);
void g_tree_remove (GTree *tree,
gconstpointer key);
gpointer g_tree_lookup (GTree *tree,
gconstpointer key);
void g_tree_traverse (GTree *tree,
GTraverseFunc traverse_func,
GTraverseType traverse_type,
gpointer data);
gpointer g_tree_search (GTree *tree,
GCompareFunc search_func,
gconstpointer data);
gint g_tree_height (GTree *tree);
gint g_tree_nnodes (GTree *tree);
G_END_DECLS

View File

@ -69,6 +69,9 @@ typedef const void *gconstpointer;
typedef gint (*GCompareFunc) (gconstpointer a,
gconstpointer b);
typedef gint (*GCompareFuncData) (gconstpointer a,
gconstpointer b,
gpointer user_data);
typedef gboolean (*GEqualFunc) (gconstpointer a,
gconstpointer b);
typedef void (*GDestroyNotify) (gpointer data);

49
glist.c
View File

@ -596,18 +596,26 @@ g_list_insert_sorted (GList *list,
}
static GList *
g_list_sort_merge (GList *l1,
GList *l2,
GCompareFunc compare_func)
g_list_sort_merge (GList *l1,
GList *l2,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GList list, *l, *lprev;
gint cmp;
l = &list;
lprev = NULL;
while (l1 && l2)
{
if (compare_func (l1->data, l2->data) < 0)
if (use_data)
cmp = ((GCompareFuncData) compare_func) (l1->data, l2->data, user_data);
else
cmp = ((GCompareFunc) compare_func) (l1->data, l2->data);
if (cmp <= 0)
{
l->next = l1;
l = l->next;
@ -631,8 +639,10 @@ g_list_sort_merge (GList *l1,
}
GList*
g_list_sort (GList *list,
GCompareFunc compare_func)
g_list_sort_real (GList *list,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GList *l1, *l2;
@ -653,9 +663,27 @@ g_list_sort (GList *list,
l2 = l1->next;
l1->next = NULL;
return g_list_sort_merge (g_list_sort (list, compare_func),
g_list_sort (l2, compare_func),
compare_func);
return g_list_sort_merge (g_list_sort_real (list, compare_func, use_data, user_data),
g_list_sort_real (l2, compare_func, use_data, user_data),
compare_func,
use_data,
user_data);
}
GList *
g_list_sort (GList *list,
GCompareFunc compare_func)
{
return g_list_sort_real (list, (GFunc) compare_func, FALSE, NULL);
}
GList *
g_list_sort_with_data (GList *list,
GCompareFuncData compare_func,
gpointer user_data)
{
return g_list_sort_real (list, (GFunc) compare_func, TRUE, user_data);
}
GList*
@ -691,7 +719,8 @@ g_list_sort2 (GList *list,
{
dst->data = g_list_sort_merge (src->data,
src->next->data,
compare_func);
(GFunc) compare_func,
FALSE, NULL);
dstprev = dst;
dst = dst->next;
src = src->next->next;

96
glist.h
View File

@ -42,52 +42,56 @@ struct _GList
/* Doubly linked lists
*/
void g_list_push_allocator (GAllocator *allocator);
void g_list_pop_allocator (void);
GList* g_list_alloc (void);
void g_list_free (GList *list);
void g_list_free_1 (GList *list);
GList* g_list_append (GList *list,
gpointer data);
GList* g_list_prepend (GList *list,
gpointer data);
GList* g_list_insert (GList *list,
gpointer data,
gint position);
GList* g_list_insert_sorted (GList *list,
gpointer data,
GCompareFunc func);
GList* g_list_concat (GList *list1,
GList *list2);
GList* g_list_remove (GList *list,
gconstpointer data);
GList* g_list_remove_link (GList *list,
GList *llink);
GList* g_list_delete_link (GList *list,
GList *link);
GList* g_list_reverse (GList *list);
GList* g_list_copy (GList *list);
GList* g_list_nth (GList *list,
guint n);
GList* g_list_find (GList *list,
gconstpointer data);
GList* g_list_find_custom (GList *list,
gconstpointer data,
GCompareFunc func);
gint g_list_position (GList *list,
GList *llink);
gint g_list_index (GList *list,
gconstpointer data);
GList* g_list_last (GList *list);
GList* g_list_first (GList *list);
guint g_list_length (GList *list);
void g_list_foreach (GList *list,
GFunc func,
gpointer user_data);
GList* g_list_sort (GList *list,
GCompareFunc compare_func);
gpointer g_list_nth_data (GList *list,
guint n);
void g_list_push_allocator (GAllocator *allocator);
void g_list_pop_allocator (void);
GList* g_list_alloc (void);
void g_list_free (GList *list);
void g_list_free_1 (GList *list);
GList* g_list_append (GList *list,
gpointer data);
GList* g_list_prepend (GList *list,
gpointer data);
GList* g_list_insert (GList *list,
gpointer data,
gint position);
GList* g_list_insert_sorted (GList *list,
gpointer data,
GCompareFunc func);
GList* g_list_concat (GList *list1,
GList *list2);
GList* g_list_remove (GList *list,
gconstpointer data);
GList* g_list_remove_link (GList *list,
GList *llink);
GList* g_list_delete_link (GList *list,
GList *link);
GList* g_list_reverse (GList *list);
GList* g_list_copy (GList *list);
GList* g_list_nth (GList *list,
guint n);
GList* g_list_find (GList *list,
gconstpointer data);
GList* g_list_find_custom (GList *list,
gconstpointer data,
GCompareFunc func);
gint g_list_position (GList *list,
GList *llink);
gint g_list_index (GList *list,
gconstpointer data);
GList* g_list_last (GList *list);
GList* g_list_first (GList *list);
guint g_list_length (GList *list);
void g_list_foreach (GList *list,
GFunc func,
gpointer user_data);
GList* g_list_sort (GList *list,
GCompareFunc compare_func);
GList* g_list_sort_with_data (GList *list,
GCompareFuncData compare_func,
gpointer user_data);
gpointer g_list_nth_data (GList *list,
guint n);
#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)

269
gqsort.c Normal file
View File

@ -0,0 +1,269 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
* Copyright (C) 2000 Eazel, Inc.
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* This file was originally part of the GNU C Library, and was modified to allow
* user data to be passed in to the sorting function.
*
* Written by Douglas C. Schmidt (schmidt@ics.uci.edu).
* Modified by Maciej Stachowiak (mjs@eazel.com)
*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/. */
#include <string.h>
#include "glib.h"
/* Byte-wise swap two items of size SIZE. */
#define SWAP(a, b, size) \
do \
{ \
register size_t __size = (size); \
register char *__a = (a), *__b = (b); \
do \
{ \
char __tmp = *__a; \
*__a++ = *__b; \
*__b++ = __tmp; \
} while (--__size > 0); \
} while (0)
/* Discontinue quicksort algorithm when partition gets below this size.
This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 4
/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct
{
char *lo;
char *hi;
}
stack_node;
/* The next 4 #defines implement a very fast in-line stack abstraction. */
#define STACK_SIZE (8 * sizeof(unsigned long int))
#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
#define STACK_NOT_EMPTY (stack < top)
/* Order size using quicksort. This implementation incorporates
* four optimizations discussed in Sedgewick:
*
* 1. Non-recursive, using an explicit stack of pointer that store the next
* array partition to sort. To save time, this maximum amount of space
* required to store an array of MAX_INT is allocated on the stack. Assuming
* a 32-bit integer, this needs only 32 * sizeof(stack_node) == 136 bits.
* Pretty cheap, actually.
*
* 2. Chose the pivot element using a median-of-three decision tree. This
* reduces the probability of selecting a bad pivot value and eliminates
* certain * extraneous comparisons.
*
* 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion
* sort to order the MAX_THRESH items within each partition. This is a big
* win, since insertion sort is faster for small, mostly sorted array
* segments.
*
* 4. The larger of the two sub-partitions is always pushed onto the stack
* first, with the algorithm then concentrating on the smaller partition.
* This *guarantees* no more than log (n) stack size is needed (actually O(1)
* in this case)!
*/
void
g_qsort_with_data (gconstpointer pbase,
gint total_elems,
size_t size,
GCompareFuncData compare_func,
gpointer user_data)
{
register char *base_ptr = (char *) pbase;
/* Allocating SIZE bytes for a pivot buffer facilitates a better
* algorithm below since we can do comparisons directly on the pivot.
*/
char *pivot_buffer = (char *) alloca (size);
const size_t max_thresh = MAX_THRESH * size;
g_return_if_fail (total_elems > 0);
g_return_if_fail (pbase != NULL);
g_return_if_fail (compare_func != NULL);
if (total_elems > MAX_THRESH)
{
char *lo = base_ptr;
char *hi = &lo[size * (total_elems - 1)];
/* Largest size needed for 32-bit int!!! */
stack_node stack[STACK_SIZE];
stack_node *top = stack + 1;
while (STACK_NOT_EMPTY)
{
char *left_ptr;
char *right_ptr;
char *pivot = pivot_buffer;
/* Select median value from among LO, MID, and HI. Rearrange
* LO and HI so the three values are sorted. This lowers the
* probability of picking a pathological pivot value and
* skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
char *mid = lo + size * ((hi - lo) / size >> 1);
if ((*compare_func) ((void *) mid, (void *) lo, user_data) < 0)
SWAP (mid, lo, size);
if ((*compare_func) ((void *) hi, (void *) mid, user_data) < 0)
SWAP (mid, hi, size);
else
goto jump_over;
if ((*compare_func) ((void *) mid, (void *) lo, user_data) < 0)
SWAP (mid, lo, size);
jump_over:;
memcpy (pivot, mid, size);
pivot = pivot_buffer;
left_ptr = lo + size;
right_ptr = hi - size;
/* Here's the famous ``collapse the walls'' section of quicksort.
* Gotta like those tight inner loops! They are the main reason
* that this algorithm runs much faster than others. */
do
{
while ((*compare_func)
((void *) left_ptr, (void *) pivot,
user_data) < 0)
left_ptr += size;
while ((*compare_func)
((void *) pivot, (void *) right_ptr,
user_data) < 0)
right_ptr -= size;
if (left_ptr < right_ptr)
{
SWAP (left_ptr, right_ptr, size);
left_ptr += size;
right_ptr -= size;
}
else if (left_ptr == right_ptr)
{
left_ptr += size;
right_ptr -= size;
break;
}
}
while (left_ptr <= right_ptr);
/* Set up pointers for next iteration. First determine whether
* left and right partitions are below the threshold size. If so,
* ignore one or both. Otherwise, push the larger partition's
* bounds on the stack and continue sorting the smaller one. */
if ((size_t) (right_ptr - lo) <= max_thresh)
{
if ((size_t) (hi - left_ptr) <= max_thresh)
/* Ignore both small partitions. */
POP (lo, hi);
else
/* Ignore small left partition. */
lo = left_ptr;
}
else if ((size_t) (hi - left_ptr) <= max_thresh)
/* Ignore small right partition. */
hi = right_ptr;
else if ((right_ptr - lo) > (hi - left_ptr))
{
/* Push larger left partition indices. */
PUSH (lo, right_ptr);
lo = left_ptr;
}
else
{
/* Push larger right partition indices. */
PUSH (left_ptr, hi);
hi = right_ptr;
}
}
}
/* Once the BASE_PTR array is partially sorted by quicksort the rest
* is completely sorted using insertion sort, since this is efficient
* for partitions below MAX_THRESH size. BASE_PTR points to the beginning
* of the array to sort, and END_PTR points at the very last element in
* the array (*not* one beyond it!). */
{
char *const end_ptr = &base_ptr[size * (total_elems - 1)];
char *tmp_ptr = base_ptr;
char *thresh = MIN (end_ptr, base_ptr + max_thresh);
register char *run_ptr;
/* Find smallest element in first threshold and place it at the
* array's beginning. This is the smallest array element,
* and the operation speeds up insertion sort's inner loop. */
for (run_ptr = tmp_ptr + size; run_ptr <= thresh;
run_ptr +=
size) if ((*compare_func) ((void *) run_ptr, (void *) tmp_ptr,
user_data) < 0)
tmp_ptr = run_ptr;
if (tmp_ptr != base_ptr)
SWAP (tmp_ptr, base_ptr, size);
/* Insertion sort, running from left-hand-side up to right-hand-side. */
run_ptr = base_ptr + size;
while ((run_ptr += size) <= end_ptr)
{
tmp_ptr = run_ptr - size;
while ((*compare_func)
((void *) run_ptr, (void *) tmp_ptr,
user_data) < 0)
tmp_ptr -= size;
tmp_ptr += size;
if (tmp_ptr != run_ptr)
{
char *trav;
trav = run_ptr + size;
while (--trav >= run_ptr)
{
char c = *trav;
char *hi, *lo;
for (hi = lo = trav;
(lo -= size) >= tmp_ptr; hi = lo)
*hi = *lo;
*hi = c;
}
}
}
}
}

44
gqsort.h Normal file
View File

@ -0,0 +1,44 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GLib Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __G_QSORT_H__
#define __G_QSORT_H__
#include <gtypes.h>
G_BEGIN_DECLS
void g_qsort_with_data (gconstpointer pbase,
gint total_elems,
size_t size,
GCompareFuncData compare_func,
gpointer user_data);
G_END_DECLS
#endif /* __G_QSORT_H__ */

View File

@ -580,18 +580,26 @@ g_slist_insert_sorted (GSList *list,
}
}
static GSList*
g_slist_sort_merge (GSList *l1,
GSList *l2,
GCompareFunc compare_func)
static GSList *
g_slist_sort_merge (GSList *l1,
GSList *l2,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GSList list, *l;
gint cmp;
l=&list;
while (l1 && l2)
{
if (compare_func(l1->data,l2->data) < 0)
if (use_data)
cmp = ((GCompareFuncData) compare_func) (l1->data, l2->data, user_data);
else
cmp = ((GCompareFunc) compare_func) (l1->data, l2->data);
if (cmp <= 0)
{
l=l->next=l1;
l1=l1->next;
@ -607,9 +615,11 @@ g_slist_sort_merge (GSList *l1,
return list.next;
}
GSList*
g_slist_sort (GSList *list,
GCompareFunc compare_func)
static GSList *
g_slist_sort_real (GSList *list,
GFunc compare_func,
gboolean use_data,
gpointer user_data)
{
GSList *l1, *l2;
@ -630,7 +640,24 @@ g_slist_sort (GSList *list,
l2 = l1->next;
l1->next = NULL;
return g_slist_sort_merge (g_slist_sort (list, compare_func),
g_slist_sort (l2, compare_func),
compare_func);
return g_slist_sort_merge (g_slist_sort_real (list, compare_func, use_data, user_data),
g_slist_sort_real (l2, compare_func, use_data, user_data),
compare_func,
use_data,
user_data);
}
GSList *
g_slist_sort (GSList *list,
GCompareFunc compare_func)
{
return g_slist_sort_real (list, (GFunc) compare_func, FALSE, NULL);
}
GSList *
g_slist_sort_with_data (GSList *list,
GCompareFuncData compare_func,
gpointer user_data)
{
return g_slist_sort_real (list, (GFunc) compare_func, TRUE, user_data);
}

View File

@ -41,54 +41,57 @@ struct _GSList
/* Singly linked lists
*/
void g_slist_push_allocator (GAllocator *allocator);
void g_slist_pop_allocator (void);
GSList* g_slist_alloc (void);
void g_slist_free (GSList *list);
void g_slist_free_1 (GSList *list);
GSList* g_slist_append (GSList *list,
gpointer data);
GSList* g_slist_prepend (GSList *list,
gpointer data);
GSList* g_slist_insert (GSList *list,
gpointer data,
gint position);
GSList* g_slist_insert_sorted (GSList *list,
gpointer data,
GCompareFunc func);
GSList* g_slist_insert_before (GSList *slist,
GSList *sibling,
gpointer data);
GSList* g_slist_concat (GSList *list1,
GSList *list2);
GSList* g_slist_remove (GSList *list,
gconstpointer data);
GSList* g_slist_remove_link (GSList *list,
GSList *link);
GSList* g_slist_delete_link (GSList *list,
GSList *link);
GSList* g_slist_reverse (GSList *list);
GSList* g_slist_copy (GSList *list);
GSList* g_slist_nth (GSList *list,
guint n);
GSList* g_slist_find (GSList *list,
gconstpointer data);
GSList* g_slist_find_custom (GSList *list,
gconstpointer data,
GCompareFunc func);
gint g_slist_position (GSList *list,
GSList *llink);
gint g_slist_index (GSList *list,
gconstpointer data);
GSList* g_slist_last (GSList *list);
guint g_slist_length (GSList *list);
void g_slist_foreach (GSList *list,
GFunc func,
gpointer user_data);
GSList* g_slist_sort (GSList *list,
GCompareFunc compare_func);
gpointer g_slist_nth_data (GSList *list,
guint n);
void g_slist_push_allocator (GAllocator *allocator);
void g_slist_pop_allocator (void);
GSList* g_slist_alloc (void);
void g_slist_free (GSList *list);
void g_slist_free_1 (GSList *list);
GSList* g_slist_append (GSList *list,
gpointer data);
GSList* g_slist_prepend (GSList *list,
gpointer data);
GSList* g_slist_insert (GSList *list,
gpointer data,
gint position);
GSList* g_slist_insert_sorted (GSList *list,
gpointer data,
GCompareFunc func);
GSList* g_slist_insert_before (GSList *slist,
GSList *sibling,
gpointer data);
GSList* g_slist_concat (GSList *list1,
GSList *list2);
GSList* g_slist_remove (GSList *list,
gconstpointer data);
GSList* g_slist_remove_link (GSList *list,
GSList *link);
GSList* g_slist_delete_link (GSList *list,
GSList *link);
GSList* g_slist_reverse (GSList *list);
GSList* g_slist_copy (GSList *list);
GSList* g_slist_nth (GSList *list,
guint n);
GSList* g_slist_find (GSList *list,
gconstpointer data);
GSList* g_slist_find_custom (GSList *list,
gconstpointer data,
GCompareFunc func);
gint g_slist_position (GSList *list,
GSList *llink);
gint g_slist_index (GSList *list,
gconstpointer data);
GSList* g_slist_last (GSList *list);
guint g_slist_length (GSList *list);
void g_slist_foreach (GSList *list,
GFunc func,
gpointer user_data);
GSList* g_slist_sort (GSList *list,
GCompareFunc compare_func);
GSList* g_slist_sort_with_data (GSList *list,
GCompareFuncData compare_func,
gpointer user_data);
gpointer g_slist_nth_data (GSList *list,
guint n);
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
G_END_DECLS

77
gtree.c
View File

@ -37,7 +37,8 @@ typedef struct _GTreeNode GTreeNode;
struct _GRealTree
{
GTreeNode *root;
GCompareFunc key_compare;
GCompareFuncData key_compare;
gpointer key_compare_data;
};
struct _GTreeNode
@ -54,12 +55,14 @@ static GTreeNode* g_tree_node_new (gpointer key,
gpointer value);
static void g_tree_node_destroy (GTreeNode *node);
static GTreeNode* g_tree_node_insert (GTreeNode *node,
GCompareFunc compare,
GCompareFuncData compare,
gpointer comp_data,
gpointer key,
gpointer value,
gint *inserted);
static GTreeNode* g_tree_node_remove (GTreeNode *node,
GCompareFunc compare,
GCompareFuncData compare,
gpointer comp_data,
gconstpointer key);
static GTreeNode* g_tree_node_balance (GTreeNode *node);
static GTreeNode* g_tree_node_remove_leftmost (GTreeNode *node,
@ -69,7 +72,8 @@ static GTreeNode* g_tree_node_restore_left_balance (GTreeNode *node,
static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
gint old_balance);
static gpointer g_tree_node_lookup (GTreeNode *node,
GCompareFunc compare,
GCompareFuncData compare,
gpointer comp_data,
gconstpointer key);
static gint g_tree_node_count (GTreeNode *node);
static gint g_tree_node_pre_order (GTreeNode *node,
@ -149,9 +153,8 @@ g_tree_node_destroy (GTreeNode *node)
}
}
GTree*
g_tree_new (GCompareFunc key_compare_func)
GTree* g_tree_new_udata(GCompareFuncData key_compare_func,
gpointer key_compare_data)
{
GRealTree *rtree;
@ -160,10 +163,18 @@ g_tree_new (GCompareFunc key_compare_func)
rtree = g_new (GRealTree, 1);
rtree->root = NULL;
rtree->key_compare = key_compare_func;
rtree->key_compare_data = key_compare_data;
return (GTree*) rtree;
}
GTree*
g_tree_new (GCompareFunc key_compare_func)
{
return g_tree_new_udata ((GCompareFuncData) key_compare_func, NULL);
}
void
g_tree_destroy (GTree *tree)
{
@ -191,6 +202,7 @@ g_tree_insert (GTree *tree,
inserted = FALSE;
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
rtree->key_compare_data,
key, value, &inserted);
}
@ -204,7 +216,8 @@ g_tree_remove (GTree *tree,
rtree = (GRealTree*) tree;
rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare, key);
rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare,
rtree->key_compare_data, key);
}
gpointer
@ -217,7 +230,8 @@ g_tree_lookup (GTree *tree,
rtree = (GRealTree*) tree;
return g_tree_node_lookup (rtree->root, rtree->key_compare, key);
return g_tree_node_lookup (rtree->root, rtree->key_compare,
rtree->key_compare_data, key);
}
void
@ -303,11 +317,12 @@ g_tree_nnodes (GTree *tree)
}
static GTreeNode*
g_tree_node_insert (GTreeNode *node,
GCompareFunc compare,
gpointer key,
gpointer value,
gint *inserted)
g_tree_node_insert (GTreeNode *node,
GCompareFuncData compare,
gpointer compare_data,
gpointer key,
gpointer value,
gint *inserted)
{
gint old_balance;
gint cmp;
@ -318,7 +333,7 @@ g_tree_node_insert (GTreeNode *node,
return g_tree_node_new (key, value);
}
cmp = (* compare) (key, node->key);
cmp = (* compare) (key, node->key, compare_data);
if (cmp == 0)
{
*inserted = FALSE;
@ -331,7 +346,8 @@ g_tree_node_insert (GTreeNode *node,
if (node->left)
{
old_balance = node->left->balance;
node->left = g_tree_node_insert (node->left, compare, key, value, inserted);
node->left = g_tree_node_insert (node->left, compare, compare_data,
key, value, inserted);
if ((old_balance != node->left->balance) && node->left->balance)
node->balance -= 1;
@ -348,7 +364,8 @@ g_tree_node_insert (GTreeNode *node,
if (node->right)
{
old_balance = node->right->balance;
node->right = g_tree_node_insert (node->right, compare, key, value, inserted);
node->right = g_tree_node_insert (node->right, compare, compare_data,
key, value, inserted);
if ((old_balance != node->right->balance) && node->right->balance)
node->balance += 1;
@ -371,9 +388,10 @@ g_tree_node_insert (GTreeNode *node,
}
static GTreeNode*
g_tree_node_remove (GTreeNode *node,
GCompareFunc compare,
gconstpointer key)
g_tree_node_remove (GTreeNode *node,
GCompareFuncData compare,
gpointer compare_data,
gconstpointer key)
{
GTreeNode *new_root;
gint old_balance;
@ -382,7 +400,7 @@ g_tree_node_remove (GTreeNode *node,
if (!node)
return NULL;
cmp = (* compare) (key, node->key);
cmp = (* compare) (key, node->key, compare_data);
if (cmp == 0)
{
GTreeNode *garbage;
@ -419,7 +437,7 @@ g_tree_node_remove (GTreeNode *node,
if (node->left)
{
old_balance = node->left->balance;
node->left = g_tree_node_remove (node->left, compare, key);
node->left = g_tree_node_remove (node->left, compare, compare_data, key);
node = g_tree_node_restore_left_balance (node, old_balance);
}
}
@ -428,7 +446,7 @@ g_tree_node_remove (GTreeNode *node,
if (node->right)
{
old_balance = node->right->balance;
node->right = g_tree_node_remove (node->right, compare, key);
node->right = g_tree_node_remove (node->right, compare, compare_data, key);
node = g_tree_node_restore_right_balance (node, old_balance);
}
}
@ -503,28 +521,29 @@ g_tree_node_restore_right_balance (GTreeNode *node,
}
static gpointer
g_tree_node_lookup (GTreeNode *node,
GCompareFunc compare,
gconstpointer key)
g_tree_node_lookup (GTreeNode *node,
GCompareFuncData compare,
gpointer compare_data,
gconstpointer key)
{
gint cmp;
if (!node)
return NULL;
cmp = (* compare) (key, node->key);
cmp = (* compare) (key, node->key, compare_data);
if (cmp == 0)
return node->value;
if (cmp < 0)
{
if (node->left)
return g_tree_node_lookup (node->left, compare, key);
return g_tree_node_lookup (node->left, compare, compare_data, key);
}
else if (cmp > 0)
{
if (node->right)
return g_tree_node_lookup (node->right, compare, key);
return g_tree_node_lookup (node->right, compare, compare_data, key);
}
return NULL;

40
gtree.h
View File

@ -39,24 +39,28 @@ typedef gint (*GTraverseFunc) (gpointer key,
/* Balanced binary trees
*/
GTree* g_tree_new (GCompareFunc key_compare_func);
void g_tree_destroy (GTree *tree);
void g_tree_insert (GTree *tree,
gpointer key,
gpointer value);
void g_tree_remove (GTree *tree,
gconstpointer key);
gpointer g_tree_lookup (GTree *tree,
gconstpointer key);
void g_tree_traverse (GTree *tree,
GTraverseFunc traverse_func,
GTraverseType traverse_type,
gpointer data);
gpointer g_tree_search (GTree *tree,
GCompareFunc search_func,
gconstpointer data);
gint g_tree_height (GTree *tree);
gint g_tree_nnodes (GTree *tree);
GTree* g_tree_new (GCompareFunc key_compare_func);
GTree* g_tree_new_with_data (GCompareFuncData key_compare_func,
gpointer user_data);
void g_tree_destroy (GTree *tree);
void g_tree_insert (GTree *tree,
gpointer key,
gpointer value);
void g_tree_remove (GTree *tree,
gconstpointer key);
gpointer g_tree_lookup (GTree *tree,
gconstpointer key);
void g_tree_traverse (GTree *tree,
GTraverseFunc traverse_func,
GTraverseType traverse_type,
gpointer data);
gpointer g_tree_search (GTree *tree,
GCompareFunc search_func,
gconstpointer data);
gint g_tree_height (GTree *tree);
gint g_tree_nnodes (GTree *tree);
G_END_DECLS

View File

@ -69,6 +69,9 @@ typedef const void *gconstpointer;
typedef gint (*GCompareFunc) (gconstpointer a,
gconstpointer b);
typedef gint (*GCompareFuncData) (gconstpointer a,
gconstpointer b,
gpointer user_data);
typedef gboolean (*GEqualFunc) (gconstpointer a,
gconstpointer b);
typedef void (*GDestroyNotify) (gpointer data);