mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-01 15:03:39 +02:00
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:
committed by
Jonathan Blandford
parent
40d62d0dd7
commit
2645aaf59c
18
ChangeLog
18
ChangeLog
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -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>
|
2000-11-16 Havoc Pennington <hp@redhat.com>
|
||||||
|
|
||||||
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
* guniprop.c (g_unichar_isspace): Use a switch here, maybe helps
|
||||||
|
@@ -66,6 +66,7 @@ libglib_1_3_la_SOURCES = \
|
|||||||
gmessages.c \
|
gmessages.c \
|
||||||
gnode.c \
|
gnode.c \
|
||||||
gprimes.c \
|
gprimes.c \
|
||||||
|
gqsort.c \
|
||||||
gqueue.c \
|
gqueue.c \
|
||||||
grel.c \
|
grel.c \
|
||||||
grand.c \
|
grand.c \
|
||||||
@@ -115,6 +116,7 @@ glibinclude_HEADERS = \
|
|||||||
gmessages.h \
|
gmessages.h \
|
||||||
gnode.h \
|
gnode.h \
|
||||||
gprimes.h \
|
gprimes.h \
|
||||||
|
gqsort.h \
|
||||||
gquark.h \
|
gquark.h \
|
||||||
gqueue.h \
|
gqueue.h \
|
||||||
grand.h \
|
grand.h \
|
||||||
|
79
garray.c
79
garray.c
@@ -29,6 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -264,6 +265,39 @@ g_array_remove_index_fast (GArray* farray,
|
|||||||
return 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
|
static gint
|
||||||
g_nearest_pow (gint num)
|
g_nearest_pow (gint num)
|
||||||
{
|
{
|
||||||
@@ -527,6 +561,34 @@ g_ptr_array_add (GPtrArray* farray,
|
|||||||
array->pdata[array->len++] = data;
|
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
|
/* Byte arrays
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -581,9 +643,24 @@ GByteArray* g_byte_array_remove_index (GByteArray *array,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
||||||
guint index)
|
guint index)
|
||||||
{
|
{
|
||||||
g_array_remove_index_fast((GArray*) array, index);
|
g_array_remove_index_fast((GArray*) array, index);
|
||||||
|
|
||||||
return array;
|
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
133
garray.h
@@ -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_insert_val(a,i,v) g_array_insert_vals (a, i, &v, 1)
|
||||||
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
|
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
|
||||||
|
|
||||||
GArray* g_array_new (gboolean zero_terminated,
|
GArray* g_array_new (gboolean zero_terminated,
|
||||||
gboolean clear,
|
gboolean clear,
|
||||||
guint element_size);
|
guint element_size);
|
||||||
GArray* g_array_sized_new (gboolean zero_terminated,
|
GArray* g_array_sized_new (gboolean zero_terminated,
|
||||||
gboolean clear,
|
gboolean clear,
|
||||||
guint element_size,
|
guint element_size,
|
||||||
guint reserved_size);
|
guint reserved_size);
|
||||||
gchar* g_array_free (GArray *array,
|
gchar* g_array_free (GArray *array,
|
||||||
gboolean free_segment);
|
gboolean free_segment);
|
||||||
GArray* g_array_append_vals (GArray *array,
|
GArray* g_array_append_vals (GArray *array,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
guint len);
|
guint len);
|
||||||
GArray* g_array_prepend_vals (GArray *array,
|
GArray* g_array_prepend_vals (GArray *array,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
guint len);
|
guint len);
|
||||||
GArray* g_array_insert_vals (GArray *array,
|
GArray* g_array_insert_vals (GArray *array,
|
||||||
guint index,
|
guint index,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
guint len);
|
guint len);
|
||||||
GArray* g_array_set_size (GArray *array,
|
GArray* g_array_set_size (GArray *array,
|
||||||
guint length);
|
guint length);
|
||||||
GArray* g_array_remove_index (GArray *array,
|
GArray* g_array_remove_index (GArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
GArray* g_array_remove_index_fast (GArray *array,
|
GArray* g_array_remove_index_fast (GArray *array,
|
||||||
guint index);
|
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
|
/* Resizable pointer array. This interface is much less complicated
|
||||||
* than the above. Add appends appends a pointer. Remove fills any
|
* than the above. Add appends appends a pointer. Remove fills any
|
||||||
* cleared spot and shortens the array. remove_fast will again distort
|
* cleared spot and shortens the array. remove_fast will again distort
|
||||||
* order.
|
* order.
|
||||||
*/
|
*/
|
||||||
#define g_ptr_array_index(array,index) (array->pdata)[index]
|
#define g_ptr_array_index(array,index) (array->pdata)[index]
|
||||||
GPtrArray* g_ptr_array_new (void);
|
GPtrArray* g_ptr_array_new (void);
|
||||||
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
||||||
gpointer* g_ptr_array_free (GPtrArray *array,
|
gpointer* g_ptr_array_free (GPtrArray *array,
|
||||||
gboolean free_seg);
|
gboolean free_seg);
|
||||||
void g_ptr_array_set_size (GPtrArray *array,
|
void g_ptr_array_set_size (GPtrArray *array,
|
||||||
gint length);
|
gint length);
|
||||||
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
gboolean g_ptr_array_remove (GPtrArray *array,
|
gboolean g_ptr_array_remove (GPtrArray *array,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
gboolean g_ptr_array_remove_fast (GPtrArray *array,
|
gboolean g_ptr_array_remove_fast (GPtrArray *array,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
void g_ptr_array_add (GPtrArray *array,
|
void g_ptr_array_add (GPtrArray *array,
|
||||||
gpointer data);
|
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,
|
/* Byte arrays, an array of guint8. Implemented as a GArray,
|
||||||
* but type-safe.
|
* but type-safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GByteArray* g_byte_array_new (void);
|
GByteArray* g_byte_array_new (void);
|
||||||
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
||||||
guint8* g_byte_array_free (GByteArray *array,
|
guint8* g_byte_array_free (GByteArray *array,
|
||||||
gboolean free_segment);
|
gboolean free_segment);
|
||||||
GByteArray* g_byte_array_append (GByteArray *array,
|
GByteArray* g_byte_array_append (GByteArray *array,
|
||||||
const guint8 *data,
|
const guint8 *data,
|
||||||
guint len);
|
guint len);
|
||||||
GByteArray* g_byte_array_prepend (GByteArray *array,
|
GByteArray* g_byte_array_prepend (GByteArray *array,
|
||||||
const guint8 *data,
|
const guint8 *data,
|
||||||
guint len);
|
guint len);
|
||||||
GByteArray* g_byte_array_set_size (GByteArray *array,
|
GByteArray* g_byte_array_set_size (GByteArray *array,
|
||||||
guint length);
|
guint length);
|
||||||
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
||||||
guint index);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
|
1
glib.h
1
glib.h
@@ -49,6 +49,7 @@
|
|||||||
#include <gmessages.h>
|
#include <gmessages.h>
|
||||||
#include <gnode.h>
|
#include <gnode.h>
|
||||||
#include <gprimes.h>
|
#include <gprimes.h>
|
||||||
|
#include <gqsort.h>
|
||||||
#include <gquark.h>
|
#include <gquark.h>
|
||||||
#include <gqueue.h>
|
#include <gqueue.h>
|
||||||
#include <grand.h>
|
#include <grand.h>
|
||||||
|
@@ -66,6 +66,7 @@ libglib_1_3_la_SOURCES = \
|
|||||||
gmessages.c \
|
gmessages.c \
|
||||||
gnode.c \
|
gnode.c \
|
||||||
gprimes.c \
|
gprimes.c \
|
||||||
|
gqsort.c \
|
||||||
gqueue.c \
|
gqueue.c \
|
||||||
grel.c \
|
grel.c \
|
||||||
grand.c \
|
grand.c \
|
||||||
@@ -115,6 +116,7 @@ glibinclude_HEADERS = \
|
|||||||
gmessages.h \
|
gmessages.h \
|
||||||
gnode.h \
|
gnode.h \
|
||||||
gprimes.h \
|
gprimes.h \
|
||||||
|
gqsort.h \
|
||||||
gquark.h \
|
gquark.h \
|
||||||
gqueue.h \
|
gqueue.h \
|
||||||
grand.h \
|
grand.h \
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -264,6 +265,39 @@ g_array_remove_index_fast (GArray* farray,
|
|||||||
return 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
|
static gint
|
||||||
g_nearest_pow (gint num)
|
g_nearest_pow (gint num)
|
||||||
{
|
{
|
||||||
@@ -527,6 +561,34 @@ g_ptr_array_add (GPtrArray* farray,
|
|||||||
array->pdata[array->len++] = data;
|
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
|
/* Byte arrays
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -581,9 +643,24 @@ GByteArray* g_byte_array_remove_index (GByteArray *array,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
||||||
guint index)
|
guint index)
|
||||||
{
|
{
|
||||||
g_array_remove_index_fast((GArray*) array, index);
|
g_array_remove_index_fast((GArray*) array, index);
|
||||||
|
|
||||||
return array;
|
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
glib/garray.h
133
glib/garray.h
@@ -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_insert_val(a,i,v) g_array_insert_vals (a, i, &v, 1)
|
||||||
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
|
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
|
||||||
|
|
||||||
GArray* g_array_new (gboolean zero_terminated,
|
GArray* g_array_new (gboolean zero_terminated,
|
||||||
gboolean clear,
|
gboolean clear,
|
||||||
guint element_size);
|
guint element_size);
|
||||||
GArray* g_array_sized_new (gboolean zero_terminated,
|
GArray* g_array_sized_new (gboolean zero_terminated,
|
||||||
gboolean clear,
|
gboolean clear,
|
||||||
guint element_size,
|
guint element_size,
|
||||||
guint reserved_size);
|
guint reserved_size);
|
||||||
gchar* g_array_free (GArray *array,
|
gchar* g_array_free (GArray *array,
|
||||||
gboolean free_segment);
|
gboolean free_segment);
|
||||||
GArray* g_array_append_vals (GArray *array,
|
GArray* g_array_append_vals (GArray *array,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
guint len);
|
guint len);
|
||||||
GArray* g_array_prepend_vals (GArray *array,
|
GArray* g_array_prepend_vals (GArray *array,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
guint len);
|
guint len);
|
||||||
GArray* g_array_insert_vals (GArray *array,
|
GArray* g_array_insert_vals (GArray *array,
|
||||||
guint index,
|
guint index,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
guint len);
|
guint len);
|
||||||
GArray* g_array_set_size (GArray *array,
|
GArray* g_array_set_size (GArray *array,
|
||||||
guint length);
|
guint length);
|
||||||
GArray* g_array_remove_index (GArray *array,
|
GArray* g_array_remove_index (GArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
GArray* g_array_remove_index_fast (GArray *array,
|
GArray* g_array_remove_index_fast (GArray *array,
|
||||||
guint index);
|
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
|
/* Resizable pointer array. This interface is much less complicated
|
||||||
* than the above. Add appends appends a pointer. Remove fills any
|
* than the above. Add appends appends a pointer. Remove fills any
|
||||||
* cleared spot and shortens the array. remove_fast will again distort
|
* cleared spot and shortens the array. remove_fast will again distort
|
||||||
* order.
|
* order.
|
||||||
*/
|
*/
|
||||||
#define g_ptr_array_index(array,index) (array->pdata)[index]
|
#define g_ptr_array_index(array,index) (array->pdata)[index]
|
||||||
GPtrArray* g_ptr_array_new (void);
|
GPtrArray* g_ptr_array_new (void);
|
||||||
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
||||||
gpointer* g_ptr_array_free (GPtrArray *array,
|
gpointer* g_ptr_array_free (GPtrArray *array,
|
||||||
gboolean free_seg);
|
gboolean free_seg);
|
||||||
void g_ptr_array_set_size (GPtrArray *array,
|
void g_ptr_array_set_size (GPtrArray *array,
|
||||||
gint length);
|
gint length);
|
||||||
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
gpointer g_ptr_array_remove_index (GPtrArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
gboolean g_ptr_array_remove (GPtrArray *array,
|
gboolean g_ptr_array_remove (GPtrArray *array,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
gboolean g_ptr_array_remove_fast (GPtrArray *array,
|
gboolean g_ptr_array_remove_fast (GPtrArray *array,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
void g_ptr_array_add (GPtrArray *array,
|
void g_ptr_array_add (GPtrArray *array,
|
||||||
gpointer data);
|
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,
|
/* Byte arrays, an array of guint8. Implemented as a GArray,
|
||||||
* but type-safe.
|
* but type-safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GByteArray* g_byte_array_new (void);
|
GByteArray* g_byte_array_new (void);
|
||||||
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
GByteArray* g_byte_array_sized_new (guint reserved_size);
|
||||||
guint8* g_byte_array_free (GByteArray *array,
|
guint8* g_byte_array_free (GByteArray *array,
|
||||||
gboolean free_segment);
|
gboolean free_segment);
|
||||||
GByteArray* g_byte_array_append (GByteArray *array,
|
GByteArray* g_byte_array_append (GByteArray *array,
|
||||||
const guint8 *data,
|
const guint8 *data,
|
||||||
guint len);
|
guint len);
|
||||||
GByteArray* g_byte_array_prepend (GByteArray *array,
|
GByteArray* g_byte_array_prepend (GByteArray *array,
|
||||||
const guint8 *data,
|
const guint8 *data,
|
||||||
guint len);
|
guint len);
|
||||||
GByteArray* g_byte_array_set_size (GByteArray *array,
|
GByteArray* g_byte_array_set_size (GByteArray *array,
|
||||||
guint length);
|
guint length);
|
||||||
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
GByteArray* g_byte_array_remove_index (GByteArray *array,
|
||||||
guint index);
|
guint index);
|
||||||
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
|
||||||
guint index);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -49,6 +49,7 @@
|
|||||||
#include <gmessages.h>
|
#include <gmessages.h>
|
||||||
#include <gnode.h>
|
#include <gnode.h>
|
||||||
#include <gprimes.h>
|
#include <gprimes.h>
|
||||||
|
#include <gqsort.h>
|
||||||
#include <gquark.h>
|
#include <gquark.h>
|
||||||
#include <gqueue.h>
|
#include <gqueue.h>
|
||||||
#include <grand.h>
|
#include <grand.h>
|
||||||
|
49
glib/glist.c
49
glib/glist.c
@@ -596,18 +596,26 @@ g_list_insert_sorted (GList *list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
g_list_sort_merge (GList *l1,
|
g_list_sort_merge (GList *l1,
|
||||||
GList *l2,
|
GList *l2,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GList list, *l, *lprev;
|
GList list, *l, *lprev;
|
||||||
|
gint cmp;
|
||||||
|
|
||||||
l = &list;
|
l = &list;
|
||||||
lprev = NULL;
|
lprev = NULL;
|
||||||
|
|
||||||
while (l1 && l2)
|
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->next = l1;
|
||||||
l = l->next;
|
l = l->next;
|
||||||
@@ -631,8 +639,10 @@ g_list_sort_merge (GList *l1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GList*
|
GList*
|
||||||
g_list_sort (GList *list,
|
g_list_sort_real (GList *list,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GList *l1, *l2;
|
GList *l1, *l2;
|
||||||
|
|
||||||
@@ -653,9 +663,27 @@ g_list_sort (GList *list,
|
|||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
l1->next = NULL;
|
l1->next = NULL;
|
||||||
|
|
||||||
return g_list_sort_merge (g_list_sort (list, compare_func),
|
return g_list_sort_merge (g_list_sort_real (list, compare_func, use_data, user_data),
|
||||||
g_list_sort (l2, compare_func),
|
g_list_sort_real (l2, compare_func, use_data, user_data),
|
||||||
compare_func);
|
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*
|
GList*
|
||||||
@@ -691,7 +719,8 @@ g_list_sort2 (GList *list,
|
|||||||
{
|
{
|
||||||
dst->data = g_list_sort_merge (src->data,
|
dst->data = g_list_sort_merge (src->data,
|
||||||
src->next->data,
|
src->next->data,
|
||||||
compare_func);
|
(GFunc) compare_func,
|
||||||
|
FALSE, NULL);
|
||||||
dstprev = dst;
|
dstprev = dst;
|
||||||
dst = dst->next;
|
dst = dst->next;
|
||||||
src = src->next->next;
|
src = src->next->next;
|
||||||
|
96
glib/glist.h
96
glib/glist.h
@@ -42,52 +42,56 @@ struct _GList
|
|||||||
|
|
||||||
/* Doubly linked lists
|
/* Doubly linked lists
|
||||||
*/
|
*/
|
||||||
void g_list_push_allocator (GAllocator *allocator);
|
void g_list_push_allocator (GAllocator *allocator);
|
||||||
void g_list_pop_allocator (void);
|
void g_list_pop_allocator (void);
|
||||||
GList* g_list_alloc (void);
|
GList* g_list_alloc (void);
|
||||||
void g_list_free (GList *list);
|
void g_list_free (GList *list);
|
||||||
void g_list_free_1 (GList *list);
|
void g_list_free_1 (GList *list);
|
||||||
GList* g_list_append (GList *list,
|
GList* g_list_append (GList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GList* g_list_prepend (GList *list,
|
GList* g_list_prepend (GList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GList* g_list_insert (GList *list,
|
GList* g_list_insert (GList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gint position);
|
gint position);
|
||||||
GList* g_list_insert_sorted (GList *list,
|
GList* g_list_insert_sorted (GList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
GList* g_list_concat (GList *list1,
|
GList* g_list_concat (GList *list1,
|
||||||
GList *list2);
|
GList *list2);
|
||||||
GList* g_list_remove (GList *list,
|
GList* g_list_remove (GList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GList* g_list_remove_link (GList *list,
|
GList* g_list_remove_link (GList *list,
|
||||||
GList *llink);
|
GList *llink);
|
||||||
GList* g_list_delete_link (GList *list,
|
GList* g_list_delete_link (GList *list,
|
||||||
GList *link);
|
GList *link);
|
||||||
GList* g_list_reverse (GList *list);
|
GList* g_list_reverse (GList *list);
|
||||||
GList* g_list_copy (GList *list);
|
GList* g_list_copy (GList *list);
|
||||||
GList* g_list_nth (GList *list,
|
GList* g_list_nth (GList *list,
|
||||||
guint n);
|
guint n);
|
||||||
GList* g_list_find (GList *list,
|
GList* g_list_find (GList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GList* g_list_find_custom (GList *list,
|
GList* g_list_find_custom (GList *list,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
gint g_list_position (GList *list,
|
gint g_list_position (GList *list,
|
||||||
GList *llink);
|
GList *llink);
|
||||||
gint g_list_index (GList *list,
|
gint g_list_index (GList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GList* g_list_last (GList *list);
|
GList* g_list_last (GList *list);
|
||||||
GList* g_list_first (GList *list);
|
GList* g_list_first (GList *list);
|
||||||
guint g_list_length (GList *list);
|
guint g_list_length (GList *list);
|
||||||
void g_list_foreach (GList *list,
|
void g_list_foreach (GList *list,
|
||||||
GFunc func,
|
GFunc func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
GList* g_list_sort (GList *list,
|
GList* g_list_sort (GList *list,
|
||||||
GCompareFunc compare_func);
|
GCompareFunc compare_func);
|
||||||
gpointer g_list_nth_data (GList *list,
|
GList* g_list_sort_with_data (GList *list,
|
||||||
guint n);
|
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_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
|
||||||
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
|
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
|
||||||
|
|
||||||
|
269
glib/gqsort.c
Normal file
269
glib/gqsort.c
Normal 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
44
glib/gqsort.h
Normal 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__ */
|
||||||
|
|
@@ -580,18 +580,26 @@ g_slist_insert_sorted (GSList *list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList*
|
static GSList *
|
||||||
g_slist_sort_merge (GSList *l1,
|
g_slist_sort_merge (GSList *l1,
|
||||||
GSList *l2,
|
GSList *l2,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSList list, *l;
|
GSList list, *l;
|
||||||
|
gint cmp;
|
||||||
|
|
||||||
l=&list;
|
l=&list;
|
||||||
|
|
||||||
while (l1 && l2)
|
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;
|
l=l->next=l1;
|
||||||
l1=l1->next;
|
l1=l1->next;
|
||||||
@@ -607,9 +615,11 @@ g_slist_sort_merge (GSList *l1,
|
|||||||
return list.next;
|
return list.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList*
|
static GSList *
|
||||||
g_slist_sort (GSList *list,
|
g_slist_sort_real (GSList *list,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSList *l1, *l2;
|
GSList *l1, *l2;
|
||||||
|
|
||||||
@@ -630,7 +640,24 @@ g_slist_sort (GSList *list,
|
|||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
l1->next = NULL;
|
l1->next = NULL;
|
||||||
|
|
||||||
return g_slist_sort_merge (g_slist_sort (list, compare_func),
|
return g_slist_sort_merge (g_slist_sort_real (list, compare_func, use_data, user_data),
|
||||||
g_slist_sort (l2, compare_func),
|
g_slist_sort_real (l2, compare_func, use_data, user_data),
|
||||||
compare_func);
|
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);
|
||||||
}
|
}
|
||||||
|
@@ -41,54 +41,57 @@ struct _GSList
|
|||||||
|
|
||||||
/* Singly linked lists
|
/* Singly linked lists
|
||||||
*/
|
*/
|
||||||
void g_slist_push_allocator (GAllocator *allocator);
|
void g_slist_push_allocator (GAllocator *allocator);
|
||||||
void g_slist_pop_allocator (void);
|
void g_slist_pop_allocator (void);
|
||||||
GSList* g_slist_alloc (void);
|
GSList* g_slist_alloc (void);
|
||||||
void g_slist_free (GSList *list);
|
void g_slist_free (GSList *list);
|
||||||
void g_slist_free_1 (GSList *list);
|
void g_slist_free_1 (GSList *list);
|
||||||
GSList* g_slist_append (GSList *list,
|
GSList* g_slist_append (GSList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_prepend (GSList *list,
|
GSList* g_slist_prepend (GSList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_insert (GSList *list,
|
GSList* g_slist_insert (GSList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gint position);
|
gint position);
|
||||||
GSList* g_slist_insert_sorted (GSList *list,
|
GSList* g_slist_insert_sorted (GSList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
GSList* g_slist_insert_before (GSList *slist,
|
GSList* g_slist_insert_before (GSList *slist,
|
||||||
GSList *sibling,
|
GSList *sibling,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_concat (GSList *list1,
|
GSList* g_slist_concat (GSList *list1,
|
||||||
GSList *list2);
|
GSList *list2);
|
||||||
GSList* g_slist_remove (GSList *list,
|
GSList* g_slist_remove (GSList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GSList* g_slist_remove_link (GSList *list,
|
GSList* g_slist_remove_link (GSList *list,
|
||||||
GSList *link);
|
GSList *link);
|
||||||
GSList* g_slist_delete_link (GSList *list,
|
GSList* g_slist_delete_link (GSList *list,
|
||||||
GSList *link);
|
GSList *link);
|
||||||
GSList* g_slist_reverse (GSList *list);
|
GSList* g_slist_reverse (GSList *list);
|
||||||
GSList* g_slist_copy (GSList *list);
|
GSList* g_slist_copy (GSList *list);
|
||||||
GSList* g_slist_nth (GSList *list,
|
GSList* g_slist_nth (GSList *list,
|
||||||
guint n);
|
guint n);
|
||||||
GSList* g_slist_find (GSList *list,
|
GSList* g_slist_find (GSList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GSList* g_slist_find_custom (GSList *list,
|
GSList* g_slist_find_custom (GSList *list,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
gint g_slist_position (GSList *list,
|
gint g_slist_position (GSList *list,
|
||||||
GSList *llink);
|
GSList *llink);
|
||||||
gint g_slist_index (GSList *list,
|
gint g_slist_index (GSList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GSList* g_slist_last (GSList *list);
|
GSList* g_slist_last (GSList *list);
|
||||||
guint g_slist_length (GSList *list);
|
guint g_slist_length (GSList *list);
|
||||||
void g_slist_foreach (GSList *list,
|
void g_slist_foreach (GSList *list,
|
||||||
GFunc func,
|
GFunc func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
GSList* g_slist_sort (GSList *list,
|
GSList* g_slist_sort (GSList *list,
|
||||||
GCompareFunc compare_func);
|
GCompareFunc compare_func);
|
||||||
gpointer g_slist_nth_data (GSList *list,
|
GSList* g_slist_sort_with_data (GSList *list,
|
||||||
guint n);
|
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)
|
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
77
glib/gtree.c
77
glib/gtree.c
@@ -37,7 +37,8 @@ typedef struct _GTreeNode GTreeNode;
|
|||||||
struct _GRealTree
|
struct _GRealTree
|
||||||
{
|
{
|
||||||
GTreeNode *root;
|
GTreeNode *root;
|
||||||
GCompareFunc key_compare;
|
GCompareFuncData key_compare;
|
||||||
|
gpointer key_compare_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GTreeNode
|
struct _GTreeNode
|
||||||
@@ -54,12 +55,14 @@ static GTreeNode* g_tree_node_new (gpointer key,
|
|||||||
gpointer value);
|
gpointer value);
|
||||||
static void g_tree_node_destroy (GTreeNode *node);
|
static void g_tree_node_destroy (GTreeNode *node);
|
||||||
static GTreeNode* g_tree_node_insert (GTreeNode *node,
|
static GTreeNode* g_tree_node_insert (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
|
gpointer comp_data,
|
||||||
gpointer key,
|
gpointer key,
|
||||||
gpointer value,
|
gpointer value,
|
||||||
gint *inserted);
|
gint *inserted);
|
||||||
static GTreeNode* g_tree_node_remove (GTreeNode *node,
|
static GTreeNode* g_tree_node_remove (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
|
gpointer comp_data,
|
||||||
gconstpointer key);
|
gconstpointer key);
|
||||||
static GTreeNode* g_tree_node_balance (GTreeNode *node);
|
static GTreeNode* g_tree_node_balance (GTreeNode *node);
|
||||||
static GTreeNode* g_tree_node_remove_leftmost (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,
|
static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
|
||||||
gint old_balance);
|
gint old_balance);
|
||||||
static gpointer g_tree_node_lookup (GTreeNode *node,
|
static gpointer g_tree_node_lookup (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
|
gpointer comp_data,
|
||||||
gconstpointer key);
|
gconstpointer key);
|
||||||
static gint g_tree_node_count (GTreeNode *node);
|
static gint g_tree_node_count (GTreeNode *node);
|
||||||
static gint g_tree_node_pre_order (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_udata(GCompareFuncData key_compare_func,
|
||||||
GTree*
|
gpointer key_compare_data)
|
||||||
g_tree_new (GCompareFunc key_compare_func)
|
|
||||||
{
|
{
|
||||||
GRealTree *rtree;
|
GRealTree *rtree;
|
||||||
|
|
||||||
@@ -160,10 +163,18 @@ g_tree_new (GCompareFunc key_compare_func)
|
|||||||
rtree = g_new (GRealTree, 1);
|
rtree = g_new (GRealTree, 1);
|
||||||
rtree->root = NULL;
|
rtree->root = NULL;
|
||||||
rtree->key_compare = key_compare_func;
|
rtree->key_compare = key_compare_func;
|
||||||
|
rtree->key_compare_data = key_compare_data;
|
||||||
|
|
||||||
return (GTree*) rtree;
|
return (GTree*) rtree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GTree*
|
||||||
|
g_tree_new (GCompareFunc key_compare_func)
|
||||||
|
{
|
||||||
|
return g_tree_new_udata ((GCompareFuncData) key_compare_func, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
g_tree_destroy (GTree *tree)
|
g_tree_destroy (GTree *tree)
|
||||||
{
|
{
|
||||||
@@ -191,6 +202,7 @@ g_tree_insert (GTree *tree,
|
|||||||
|
|
||||||
inserted = FALSE;
|
inserted = FALSE;
|
||||||
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
|
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
|
||||||
|
rtree->key_compare_data,
|
||||||
key, value, &inserted);
|
key, value, &inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +216,8 @@ g_tree_remove (GTree *tree,
|
|||||||
|
|
||||||
rtree = (GRealTree*) 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
|
gpointer
|
||||||
@@ -217,7 +230,8 @@ g_tree_lookup (GTree *tree,
|
|||||||
|
|
||||||
rtree = (GRealTree*) 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
|
void
|
||||||
@@ -303,11 +317,12 @@ g_tree_nnodes (GTree *tree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GTreeNode*
|
static GTreeNode*
|
||||||
g_tree_node_insert (GTreeNode *node,
|
g_tree_node_insert (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
gpointer key,
|
gpointer compare_data,
|
||||||
gpointer value,
|
gpointer key,
|
||||||
gint *inserted)
|
gpointer value,
|
||||||
|
gint *inserted)
|
||||||
{
|
{
|
||||||
gint old_balance;
|
gint old_balance;
|
||||||
gint cmp;
|
gint cmp;
|
||||||
@@ -318,7 +333,7 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
return g_tree_node_new (key, value);
|
return g_tree_node_new (key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp = (* compare) (key, node->key);
|
cmp = (* compare) (key, node->key, compare_data);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
*inserted = FALSE;
|
*inserted = FALSE;
|
||||||
@@ -331,7 +346,8 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
if (node->left)
|
if (node->left)
|
||||||
{
|
{
|
||||||
old_balance = node->left->balance;
|
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)
|
if ((old_balance != node->left->balance) && node->left->balance)
|
||||||
node->balance -= 1;
|
node->balance -= 1;
|
||||||
@@ -348,7 +364,8 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
if (node->right)
|
if (node->right)
|
||||||
{
|
{
|
||||||
old_balance = node->right->balance;
|
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)
|
if ((old_balance != node->right->balance) && node->right->balance)
|
||||||
node->balance += 1;
|
node->balance += 1;
|
||||||
@@ -371,9 +388,10 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GTreeNode*
|
static GTreeNode*
|
||||||
g_tree_node_remove (GTreeNode *node,
|
g_tree_node_remove (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
gconstpointer key)
|
gpointer compare_data,
|
||||||
|
gconstpointer key)
|
||||||
{
|
{
|
||||||
GTreeNode *new_root;
|
GTreeNode *new_root;
|
||||||
gint old_balance;
|
gint old_balance;
|
||||||
@@ -382,7 +400,7 @@ g_tree_node_remove (GTreeNode *node,
|
|||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cmp = (* compare) (key, node->key);
|
cmp = (* compare) (key, node->key, compare_data);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
GTreeNode *garbage;
|
GTreeNode *garbage;
|
||||||
@@ -419,7 +437,7 @@ g_tree_node_remove (GTreeNode *node,
|
|||||||
if (node->left)
|
if (node->left)
|
||||||
{
|
{
|
||||||
old_balance = node->left->balance;
|
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);
|
node = g_tree_node_restore_left_balance (node, old_balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,7 +446,7 @@ g_tree_node_remove (GTreeNode *node,
|
|||||||
if (node->right)
|
if (node->right)
|
||||||
{
|
{
|
||||||
old_balance = node->right->balance;
|
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);
|
node = g_tree_node_restore_right_balance (node, old_balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,28 +521,29 @@ g_tree_node_restore_right_balance (GTreeNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
g_tree_node_lookup (GTreeNode *node,
|
g_tree_node_lookup (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
gconstpointer key)
|
gpointer compare_data,
|
||||||
|
gconstpointer key)
|
||||||
{
|
{
|
||||||
gint cmp;
|
gint cmp;
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cmp = (* compare) (key, node->key);
|
cmp = (* compare) (key, node->key, compare_data);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
return node->value;
|
return node->value;
|
||||||
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
if (node->left)
|
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)
|
else if (cmp > 0)
|
||||||
{
|
{
|
||||||
if (node->right)
|
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;
|
return NULL;
|
||||||
|
40
glib/gtree.h
40
glib/gtree.h
@@ -39,24 +39,28 @@ typedef gint (*GTraverseFunc) (gpointer key,
|
|||||||
|
|
||||||
/* Balanced binary trees
|
/* Balanced binary trees
|
||||||
*/
|
*/
|
||||||
GTree* g_tree_new (GCompareFunc key_compare_func);
|
GTree* g_tree_new (GCompareFunc key_compare_func);
|
||||||
void g_tree_destroy (GTree *tree);
|
GTree* g_tree_new_with_data (GCompareFuncData key_compare_func,
|
||||||
void g_tree_insert (GTree *tree,
|
gpointer user_data);
|
||||||
gpointer key,
|
void g_tree_destroy (GTree *tree);
|
||||||
gpointer value);
|
void g_tree_insert (GTree *tree,
|
||||||
void g_tree_remove (GTree *tree,
|
gpointer key,
|
||||||
gconstpointer key);
|
gpointer value);
|
||||||
gpointer g_tree_lookup (GTree *tree,
|
void g_tree_remove (GTree *tree,
|
||||||
gconstpointer key);
|
gconstpointer key);
|
||||||
void g_tree_traverse (GTree *tree,
|
gpointer g_tree_lookup (GTree *tree,
|
||||||
GTraverseFunc traverse_func,
|
gconstpointer key);
|
||||||
GTraverseType traverse_type,
|
void g_tree_traverse (GTree *tree,
|
||||||
gpointer data);
|
GTraverseFunc traverse_func,
|
||||||
gpointer g_tree_search (GTree *tree,
|
GTraverseType traverse_type,
|
||||||
GCompareFunc search_func,
|
gpointer data);
|
||||||
gconstpointer data);
|
gpointer g_tree_search (GTree *tree,
|
||||||
gint g_tree_height (GTree *tree);
|
GCompareFunc search_func,
|
||||||
gint g_tree_nnodes (GTree *tree);
|
gconstpointer data);
|
||||||
|
gint g_tree_height (GTree *tree);
|
||||||
|
gint g_tree_nnodes (GTree *tree);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -69,6 +69,9 @@ typedef const void *gconstpointer;
|
|||||||
|
|
||||||
typedef gint (*GCompareFunc) (gconstpointer a,
|
typedef gint (*GCompareFunc) (gconstpointer a,
|
||||||
gconstpointer b);
|
gconstpointer b);
|
||||||
|
typedef gint (*GCompareFuncData) (gconstpointer a,
|
||||||
|
gconstpointer b,
|
||||||
|
gpointer user_data);
|
||||||
typedef gboolean (*GEqualFunc) (gconstpointer a,
|
typedef gboolean (*GEqualFunc) (gconstpointer a,
|
||||||
gconstpointer b);
|
gconstpointer b);
|
||||||
typedef void (*GDestroyNotify) (gpointer data);
|
typedef void (*GDestroyNotify) (gpointer data);
|
||||||
|
49
glist.c
49
glist.c
@@ -596,18 +596,26 @@ g_list_insert_sorted (GList *list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
g_list_sort_merge (GList *l1,
|
g_list_sort_merge (GList *l1,
|
||||||
GList *l2,
|
GList *l2,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GList list, *l, *lprev;
|
GList list, *l, *lprev;
|
||||||
|
gint cmp;
|
||||||
|
|
||||||
l = &list;
|
l = &list;
|
||||||
lprev = NULL;
|
lprev = NULL;
|
||||||
|
|
||||||
while (l1 && l2)
|
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->next = l1;
|
||||||
l = l->next;
|
l = l->next;
|
||||||
@@ -631,8 +639,10 @@ g_list_sort_merge (GList *l1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GList*
|
GList*
|
||||||
g_list_sort (GList *list,
|
g_list_sort_real (GList *list,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GList *l1, *l2;
|
GList *l1, *l2;
|
||||||
|
|
||||||
@@ -653,9 +663,27 @@ g_list_sort (GList *list,
|
|||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
l1->next = NULL;
|
l1->next = NULL;
|
||||||
|
|
||||||
return g_list_sort_merge (g_list_sort (list, compare_func),
|
return g_list_sort_merge (g_list_sort_real (list, compare_func, use_data, user_data),
|
||||||
g_list_sort (l2, compare_func),
|
g_list_sort_real (l2, compare_func, use_data, user_data),
|
||||||
compare_func);
|
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*
|
GList*
|
||||||
@@ -691,7 +719,8 @@ g_list_sort2 (GList *list,
|
|||||||
{
|
{
|
||||||
dst->data = g_list_sort_merge (src->data,
|
dst->data = g_list_sort_merge (src->data,
|
||||||
src->next->data,
|
src->next->data,
|
||||||
compare_func);
|
(GFunc) compare_func,
|
||||||
|
FALSE, NULL);
|
||||||
dstprev = dst;
|
dstprev = dst;
|
||||||
dst = dst->next;
|
dst = dst->next;
|
||||||
src = src->next->next;
|
src = src->next->next;
|
||||||
|
96
glist.h
96
glist.h
@@ -42,52 +42,56 @@ struct _GList
|
|||||||
|
|
||||||
/* Doubly linked lists
|
/* Doubly linked lists
|
||||||
*/
|
*/
|
||||||
void g_list_push_allocator (GAllocator *allocator);
|
void g_list_push_allocator (GAllocator *allocator);
|
||||||
void g_list_pop_allocator (void);
|
void g_list_pop_allocator (void);
|
||||||
GList* g_list_alloc (void);
|
GList* g_list_alloc (void);
|
||||||
void g_list_free (GList *list);
|
void g_list_free (GList *list);
|
||||||
void g_list_free_1 (GList *list);
|
void g_list_free_1 (GList *list);
|
||||||
GList* g_list_append (GList *list,
|
GList* g_list_append (GList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GList* g_list_prepend (GList *list,
|
GList* g_list_prepend (GList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GList* g_list_insert (GList *list,
|
GList* g_list_insert (GList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gint position);
|
gint position);
|
||||||
GList* g_list_insert_sorted (GList *list,
|
GList* g_list_insert_sorted (GList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
GList* g_list_concat (GList *list1,
|
GList* g_list_concat (GList *list1,
|
||||||
GList *list2);
|
GList *list2);
|
||||||
GList* g_list_remove (GList *list,
|
GList* g_list_remove (GList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GList* g_list_remove_link (GList *list,
|
GList* g_list_remove_link (GList *list,
|
||||||
GList *llink);
|
GList *llink);
|
||||||
GList* g_list_delete_link (GList *list,
|
GList* g_list_delete_link (GList *list,
|
||||||
GList *link);
|
GList *link);
|
||||||
GList* g_list_reverse (GList *list);
|
GList* g_list_reverse (GList *list);
|
||||||
GList* g_list_copy (GList *list);
|
GList* g_list_copy (GList *list);
|
||||||
GList* g_list_nth (GList *list,
|
GList* g_list_nth (GList *list,
|
||||||
guint n);
|
guint n);
|
||||||
GList* g_list_find (GList *list,
|
GList* g_list_find (GList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GList* g_list_find_custom (GList *list,
|
GList* g_list_find_custom (GList *list,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
gint g_list_position (GList *list,
|
gint g_list_position (GList *list,
|
||||||
GList *llink);
|
GList *llink);
|
||||||
gint g_list_index (GList *list,
|
gint g_list_index (GList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GList* g_list_last (GList *list);
|
GList* g_list_last (GList *list);
|
||||||
GList* g_list_first (GList *list);
|
GList* g_list_first (GList *list);
|
||||||
guint g_list_length (GList *list);
|
guint g_list_length (GList *list);
|
||||||
void g_list_foreach (GList *list,
|
void g_list_foreach (GList *list,
|
||||||
GFunc func,
|
GFunc func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
GList* g_list_sort (GList *list,
|
GList* g_list_sort (GList *list,
|
||||||
GCompareFunc compare_func);
|
GCompareFunc compare_func);
|
||||||
gpointer g_list_nth_data (GList *list,
|
GList* g_list_sort_with_data (GList *list,
|
||||||
guint n);
|
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_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
|
||||||
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
|
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
|
||||||
|
|
||||||
|
269
gqsort.c
Normal file
269
gqsort.c
Normal 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
44
gqsort.h
Normal 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__ */
|
||||||
|
|
49
gslist.c
49
gslist.c
@@ -580,18 +580,26 @@ g_slist_insert_sorted (GSList *list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSList*
|
static GSList *
|
||||||
g_slist_sort_merge (GSList *l1,
|
g_slist_sort_merge (GSList *l1,
|
||||||
GSList *l2,
|
GSList *l2,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSList list, *l;
|
GSList list, *l;
|
||||||
|
gint cmp;
|
||||||
|
|
||||||
l=&list;
|
l=&list;
|
||||||
|
|
||||||
while (l1 && l2)
|
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;
|
l=l->next=l1;
|
||||||
l1=l1->next;
|
l1=l1->next;
|
||||||
@@ -607,9 +615,11 @@ g_slist_sort_merge (GSList *l1,
|
|||||||
return list.next;
|
return list.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSList*
|
static GSList *
|
||||||
g_slist_sort (GSList *list,
|
g_slist_sort_real (GSList *list,
|
||||||
GCompareFunc compare_func)
|
GFunc compare_func,
|
||||||
|
gboolean use_data,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSList *l1, *l2;
|
GSList *l1, *l2;
|
||||||
|
|
||||||
@@ -630,7 +640,24 @@ g_slist_sort (GSList *list,
|
|||||||
l2 = l1->next;
|
l2 = l1->next;
|
||||||
l1->next = NULL;
|
l1->next = NULL;
|
||||||
|
|
||||||
return g_slist_sort_merge (g_slist_sort (list, compare_func),
|
return g_slist_sort_merge (g_slist_sort_real (list, compare_func, use_data, user_data),
|
||||||
g_slist_sort (l2, compare_func),
|
g_slist_sort_real (l2, compare_func, use_data, user_data),
|
||||||
compare_func);
|
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);
|
||||||
}
|
}
|
||||||
|
99
gslist.h
99
gslist.h
@@ -41,54 +41,57 @@ struct _GSList
|
|||||||
|
|
||||||
/* Singly linked lists
|
/* Singly linked lists
|
||||||
*/
|
*/
|
||||||
void g_slist_push_allocator (GAllocator *allocator);
|
void g_slist_push_allocator (GAllocator *allocator);
|
||||||
void g_slist_pop_allocator (void);
|
void g_slist_pop_allocator (void);
|
||||||
GSList* g_slist_alloc (void);
|
GSList* g_slist_alloc (void);
|
||||||
void g_slist_free (GSList *list);
|
void g_slist_free (GSList *list);
|
||||||
void g_slist_free_1 (GSList *list);
|
void g_slist_free_1 (GSList *list);
|
||||||
GSList* g_slist_append (GSList *list,
|
GSList* g_slist_append (GSList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_prepend (GSList *list,
|
GSList* g_slist_prepend (GSList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_insert (GSList *list,
|
GSList* g_slist_insert (GSList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gint position);
|
gint position);
|
||||||
GSList* g_slist_insert_sorted (GSList *list,
|
GSList* g_slist_insert_sorted (GSList *list,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
GSList* g_slist_insert_before (GSList *slist,
|
GSList* g_slist_insert_before (GSList *slist,
|
||||||
GSList *sibling,
|
GSList *sibling,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_concat (GSList *list1,
|
GSList* g_slist_concat (GSList *list1,
|
||||||
GSList *list2);
|
GSList *list2);
|
||||||
GSList* g_slist_remove (GSList *list,
|
GSList* g_slist_remove (GSList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GSList* g_slist_remove_link (GSList *list,
|
GSList* g_slist_remove_link (GSList *list,
|
||||||
GSList *link);
|
GSList *link);
|
||||||
GSList* g_slist_delete_link (GSList *list,
|
GSList* g_slist_delete_link (GSList *list,
|
||||||
GSList *link);
|
GSList *link);
|
||||||
GSList* g_slist_reverse (GSList *list);
|
GSList* g_slist_reverse (GSList *list);
|
||||||
GSList* g_slist_copy (GSList *list);
|
GSList* g_slist_copy (GSList *list);
|
||||||
GSList* g_slist_nth (GSList *list,
|
GSList* g_slist_nth (GSList *list,
|
||||||
guint n);
|
guint n);
|
||||||
GSList* g_slist_find (GSList *list,
|
GSList* g_slist_find (GSList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GSList* g_slist_find_custom (GSList *list,
|
GSList* g_slist_find_custom (GSList *list,
|
||||||
gconstpointer data,
|
gconstpointer data,
|
||||||
GCompareFunc func);
|
GCompareFunc func);
|
||||||
gint g_slist_position (GSList *list,
|
gint g_slist_position (GSList *list,
|
||||||
GSList *llink);
|
GSList *llink);
|
||||||
gint g_slist_index (GSList *list,
|
gint g_slist_index (GSList *list,
|
||||||
gconstpointer data);
|
gconstpointer data);
|
||||||
GSList* g_slist_last (GSList *list);
|
GSList* g_slist_last (GSList *list);
|
||||||
guint g_slist_length (GSList *list);
|
guint g_slist_length (GSList *list);
|
||||||
void g_slist_foreach (GSList *list,
|
void g_slist_foreach (GSList *list,
|
||||||
GFunc func,
|
GFunc func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
GSList* g_slist_sort (GSList *list,
|
GSList* g_slist_sort (GSList *list,
|
||||||
GCompareFunc compare_func);
|
GCompareFunc compare_func);
|
||||||
gpointer g_slist_nth_data (GSList *list,
|
GSList* g_slist_sort_with_data (GSList *list,
|
||||||
guint n);
|
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)
|
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
77
gtree.c
77
gtree.c
@@ -37,7 +37,8 @@ typedef struct _GTreeNode GTreeNode;
|
|||||||
struct _GRealTree
|
struct _GRealTree
|
||||||
{
|
{
|
||||||
GTreeNode *root;
|
GTreeNode *root;
|
||||||
GCompareFunc key_compare;
|
GCompareFuncData key_compare;
|
||||||
|
gpointer key_compare_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GTreeNode
|
struct _GTreeNode
|
||||||
@@ -54,12 +55,14 @@ static GTreeNode* g_tree_node_new (gpointer key,
|
|||||||
gpointer value);
|
gpointer value);
|
||||||
static void g_tree_node_destroy (GTreeNode *node);
|
static void g_tree_node_destroy (GTreeNode *node);
|
||||||
static GTreeNode* g_tree_node_insert (GTreeNode *node,
|
static GTreeNode* g_tree_node_insert (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
|
gpointer comp_data,
|
||||||
gpointer key,
|
gpointer key,
|
||||||
gpointer value,
|
gpointer value,
|
||||||
gint *inserted);
|
gint *inserted);
|
||||||
static GTreeNode* g_tree_node_remove (GTreeNode *node,
|
static GTreeNode* g_tree_node_remove (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
|
gpointer comp_data,
|
||||||
gconstpointer key);
|
gconstpointer key);
|
||||||
static GTreeNode* g_tree_node_balance (GTreeNode *node);
|
static GTreeNode* g_tree_node_balance (GTreeNode *node);
|
||||||
static GTreeNode* g_tree_node_remove_leftmost (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,
|
static GTreeNode* g_tree_node_restore_right_balance (GTreeNode *node,
|
||||||
gint old_balance);
|
gint old_balance);
|
||||||
static gpointer g_tree_node_lookup (GTreeNode *node,
|
static gpointer g_tree_node_lookup (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
|
gpointer comp_data,
|
||||||
gconstpointer key);
|
gconstpointer key);
|
||||||
static gint g_tree_node_count (GTreeNode *node);
|
static gint g_tree_node_count (GTreeNode *node);
|
||||||
static gint g_tree_node_pre_order (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_udata(GCompareFuncData key_compare_func,
|
||||||
GTree*
|
gpointer key_compare_data)
|
||||||
g_tree_new (GCompareFunc key_compare_func)
|
|
||||||
{
|
{
|
||||||
GRealTree *rtree;
|
GRealTree *rtree;
|
||||||
|
|
||||||
@@ -160,10 +163,18 @@ g_tree_new (GCompareFunc key_compare_func)
|
|||||||
rtree = g_new (GRealTree, 1);
|
rtree = g_new (GRealTree, 1);
|
||||||
rtree->root = NULL;
|
rtree->root = NULL;
|
||||||
rtree->key_compare = key_compare_func;
|
rtree->key_compare = key_compare_func;
|
||||||
|
rtree->key_compare_data = key_compare_data;
|
||||||
|
|
||||||
return (GTree*) rtree;
|
return (GTree*) rtree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GTree*
|
||||||
|
g_tree_new (GCompareFunc key_compare_func)
|
||||||
|
{
|
||||||
|
return g_tree_new_udata ((GCompareFuncData) key_compare_func, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
g_tree_destroy (GTree *tree)
|
g_tree_destroy (GTree *tree)
|
||||||
{
|
{
|
||||||
@@ -191,6 +202,7 @@ g_tree_insert (GTree *tree,
|
|||||||
|
|
||||||
inserted = FALSE;
|
inserted = FALSE;
|
||||||
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
|
rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
|
||||||
|
rtree->key_compare_data,
|
||||||
key, value, &inserted);
|
key, value, &inserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +216,8 @@ g_tree_remove (GTree *tree,
|
|||||||
|
|
||||||
rtree = (GRealTree*) 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
|
gpointer
|
||||||
@@ -217,7 +230,8 @@ g_tree_lookup (GTree *tree,
|
|||||||
|
|
||||||
rtree = (GRealTree*) 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
|
void
|
||||||
@@ -303,11 +317,12 @@ g_tree_nnodes (GTree *tree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GTreeNode*
|
static GTreeNode*
|
||||||
g_tree_node_insert (GTreeNode *node,
|
g_tree_node_insert (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
gpointer key,
|
gpointer compare_data,
|
||||||
gpointer value,
|
gpointer key,
|
||||||
gint *inserted)
|
gpointer value,
|
||||||
|
gint *inserted)
|
||||||
{
|
{
|
||||||
gint old_balance;
|
gint old_balance;
|
||||||
gint cmp;
|
gint cmp;
|
||||||
@@ -318,7 +333,7 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
return g_tree_node_new (key, value);
|
return g_tree_node_new (key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmp = (* compare) (key, node->key);
|
cmp = (* compare) (key, node->key, compare_data);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
*inserted = FALSE;
|
*inserted = FALSE;
|
||||||
@@ -331,7 +346,8 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
if (node->left)
|
if (node->left)
|
||||||
{
|
{
|
||||||
old_balance = node->left->balance;
|
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)
|
if ((old_balance != node->left->balance) && node->left->balance)
|
||||||
node->balance -= 1;
|
node->balance -= 1;
|
||||||
@@ -348,7 +364,8 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
if (node->right)
|
if (node->right)
|
||||||
{
|
{
|
||||||
old_balance = node->right->balance;
|
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)
|
if ((old_balance != node->right->balance) && node->right->balance)
|
||||||
node->balance += 1;
|
node->balance += 1;
|
||||||
@@ -371,9 +388,10 @@ g_tree_node_insert (GTreeNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GTreeNode*
|
static GTreeNode*
|
||||||
g_tree_node_remove (GTreeNode *node,
|
g_tree_node_remove (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
gconstpointer key)
|
gpointer compare_data,
|
||||||
|
gconstpointer key)
|
||||||
{
|
{
|
||||||
GTreeNode *new_root;
|
GTreeNode *new_root;
|
||||||
gint old_balance;
|
gint old_balance;
|
||||||
@@ -382,7 +400,7 @@ g_tree_node_remove (GTreeNode *node,
|
|||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cmp = (* compare) (key, node->key);
|
cmp = (* compare) (key, node->key, compare_data);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
GTreeNode *garbage;
|
GTreeNode *garbage;
|
||||||
@@ -419,7 +437,7 @@ g_tree_node_remove (GTreeNode *node,
|
|||||||
if (node->left)
|
if (node->left)
|
||||||
{
|
{
|
||||||
old_balance = node->left->balance;
|
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);
|
node = g_tree_node_restore_left_balance (node, old_balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,7 +446,7 @@ g_tree_node_remove (GTreeNode *node,
|
|||||||
if (node->right)
|
if (node->right)
|
||||||
{
|
{
|
||||||
old_balance = node->right->balance;
|
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);
|
node = g_tree_node_restore_right_balance (node, old_balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,28 +521,29 @@ g_tree_node_restore_right_balance (GTreeNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
g_tree_node_lookup (GTreeNode *node,
|
g_tree_node_lookup (GTreeNode *node,
|
||||||
GCompareFunc compare,
|
GCompareFuncData compare,
|
||||||
gconstpointer key)
|
gpointer compare_data,
|
||||||
|
gconstpointer key)
|
||||||
{
|
{
|
||||||
gint cmp;
|
gint cmp;
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cmp = (* compare) (key, node->key);
|
cmp = (* compare) (key, node->key, compare_data);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
return node->value;
|
return node->value;
|
||||||
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
if (node->left)
|
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)
|
else if (cmp > 0)
|
||||||
{
|
{
|
||||||
if (node->right)
|
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;
|
return NULL;
|
||||||
|
40
gtree.h
40
gtree.h
@@ -39,24 +39,28 @@ typedef gint (*GTraverseFunc) (gpointer key,
|
|||||||
|
|
||||||
/* Balanced binary trees
|
/* Balanced binary trees
|
||||||
*/
|
*/
|
||||||
GTree* g_tree_new (GCompareFunc key_compare_func);
|
GTree* g_tree_new (GCompareFunc key_compare_func);
|
||||||
void g_tree_destroy (GTree *tree);
|
GTree* g_tree_new_with_data (GCompareFuncData key_compare_func,
|
||||||
void g_tree_insert (GTree *tree,
|
gpointer user_data);
|
||||||
gpointer key,
|
void g_tree_destroy (GTree *tree);
|
||||||
gpointer value);
|
void g_tree_insert (GTree *tree,
|
||||||
void g_tree_remove (GTree *tree,
|
gpointer key,
|
||||||
gconstpointer key);
|
gpointer value);
|
||||||
gpointer g_tree_lookup (GTree *tree,
|
void g_tree_remove (GTree *tree,
|
||||||
gconstpointer key);
|
gconstpointer key);
|
||||||
void g_tree_traverse (GTree *tree,
|
gpointer g_tree_lookup (GTree *tree,
|
||||||
GTraverseFunc traverse_func,
|
gconstpointer key);
|
||||||
GTraverseType traverse_type,
|
void g_tree_traverse (GTree *tree,
|
||||||
gpointer data);
|
GTraverseFunc traverse_func,
|
||||||
gpointer g_tree_search (GTree *tree,
|
GTraverseType traverse_type,
|
||||||
GCompareFunc search_func,
|
gpointer data);
|
||||||
gconstpointer data);
|
gpointer g_tree_search (GTree *tree,
|
||||||
gint g_tree_height (GTree *tree);
|
GCompareFunc search_func,
|
||||||
gint g_tree_nnodes (GTree *tree);
|
gconstpointer data);
|
||||||
|
gint g_tree_height (GTree *tree);
|
||||||
|
gint g_tree_nnodes (GTree *tree);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
3
gtypes.h
3
gtypes.h
@@ -69,6 +69,9 @@ typedef const void *gconstpointer;
|
|||||||
|
|
||||||
typedef gint (*GCompareFunc) (gconstpointer a,
|
typedef gint (*GCompareFunc) (gconstpointer a,
|
||||||
gconstpointer b);
|
gconstpointer b);
|
||||||
|
typedef gint (*GCompareFuncData) (gconstpointer a,
|
||||||
|
gconstpointer b,
|
||||||
|
gpointer user_data);
|
||||||
typedef gboolean (*GEqualFunc) (gconstpointer a,
|
typedef gboolean (*GEqualFunc) (gconstpointer a,
|
||||||
gconstpointer b);
|
gconstpointer b);
|
||||||
typedef void (*GDestroyNotify) (gpointer data);
|
typedef void (*GDestroyNotify) (gpointer data);
|
||||||
|
Reference in New Issue
Block a user