From cf1f9484225530d531a3e52fb9b78102431bf3d8 Mon Sep 17 00:00:00 2001 From: Serj Kalichev Date: Mon, 26 Mar 2012 11:04:13 -0400 Subject: [PATCH] glib-local: add local glib functions While adding the configure enhancements, I forgot to stage the glib-local changes, so they weren't pushed. This patch adds them Signed-off-by: Serj Kalichev Signed-off-by: Neil Horman --- glib-local/Makefile.am | 8 + glib-local/glib.h | 1 + glib-local/glist.c | 381 +++++++++++++++++++++++++++++++++++++++++ glib-local/glist.h | 56 ++++++ 4 files changed, 446 insertions(+) create mode 100644 glib-local/Makefile.am create mode 100644 glib-local/glib.h create mode 100644 glib-local/glist.c create mode 100644 glib-local/glist.h diff --git a/glib-local/Makefile.am b/glib-local/Makefile.am new file mode 100644 index 0000000..336b56e --- /dev/null +++ b/glib-local/Makefile.am @@ -0,0 +1,8 @@ +## Process this file with automake to produce Makefile.in +noinst_LIBRARIES = libglib.a + +libglib_a_SOURCES = glist.c + +libglib_a_CFLAGS = @GLIB_CFLAGS@ + +noinst_HEADERS = glib.h glist.h diff --git a/glib-local/glib.h b/glib-local/glib.h new file mode 100644 index 0000000..5874892 --- /dev/null +++ b/glib-local/glib.h @@ -0,0 +1 @@ +#include diff --git a/glib-local/glist.c b/glib-local/glist.c new file mode 100644 index 0000000..6fa1761 --- /dev/null +++ b/glib-local/glist.c @@ -0,0 +1,381 @@ +#include + +#include "glist.h" + +/** + * g_list_free: + * @list: a #GList + * + * Frees all of the memory used by a #GList. + * The freed elements are returned to the slice allocator. + * + * + * If list elements contain dynamically-allocated memory, + * you should either use g_list_free_full() or free them manually + * first. + * + */ +void +g_list_free (GList *list) +{ + GList *l = list; + + while(l) { + GList *tmp = l->next; + free(l); + l = tmp; + } +} + +/** + * g_list_last: + * @list: a #GList + * + * Gets the last element in a #GList. + * + * Returns: the last element in the #GList, + * or %NULL if the #GList has no elements + */ +GList* +g_list_last (GList *list) +{ + if (list) + { + while (list->next) + list = list->next; + } + + return list; +} + +/** + * g_list_append: + * @list: a pointer to a #GList + * @data: the data for the new element + * + * Adds a new element on to the end of the list. + * + * + * The return value is the new start of the list, which + * may have changed, so make sure you store the new value. + * + * + * + * Note that g_list_append() has to traverse the entire list + * to find the end, which is inefficient when adding multiple + * elements. A common idiom to avoid the inefficiency is to prepend + * the elements and reverse the list when all elements have been added. + * + * + * |[ + * /* Notice that these are initialized to the empty list. */ + * GList *list = NULL, *number_list = NULL; + * + * /* This is a list of strings. */ + * list = g_list_append (list, "first"); + * list = g_list_append (list, "second"); + * + * /* This is a list of integers. */ + * number_list = g_list_append (number_list, GINT_TO_POINTER (27)); + * number_list = g_list_append (number_list, GINT_TO_POINTER (14)); + * ]| + * + * Returns: the new start of the #GList + */ +GList* +g_list_append (GList *list, + gpointer data) +{ + GList *new_list; + GList *last; + + new_list = malloc(sizeof(*new_list)); + new_list->data = data; + new_list->next = NULL; + + if (list) + { + last = g_list_last (list); + /* g_assert (last != NULL); */ + last->next = new_list; + new_list->prev = last; + + return list; + } + else + { + new_list->prev = NULL; + return new_list; + } +} + +static inline GList* +_g_list_remove_link (GList *list, + GList *link) +{ + if (link) + { + if (link->prev) + link->prev->next = link->next; + if (link->next) + link->next->prev = link->prev; + + if (link == list) + list = list->next; + + link->next = NULL; + link->prev = NULL; + } + + return list; +} + +/** + * g_list_delete_link: + * @list: a #GList + * @link_: node to delete from @list + * + * Removes the node link_ from the list and frees it. + * Compare this to g_list_remove_link() which removes the node + * without freeing it. + * + * Returns: the new head of @list + */ +GList* +g_list_delete_link (GList *list, + GList *link_) +{ + list = _g_list_remove_link (list, link_); + free (link_); + + return list; +} + +/** + * g_list_first: + * @list: a #GList + * + * Gets the first element in a #GList. + * + * Returns: the first element in the #GList, + * or %NULL if the #GList has no elements + */ +GList* +g_list_first (GList *list) +{ + if (list) + { + while (list->prev) + list = list->prev; + } + + return list; +} + +static GList * +g_list_sort_merge (GList *l1, + GList *l2, + GFunc compare_func, + gpointer user_data) +{ + GList list, *l, *lprev; + gint cmp; + + l = &list; + lprev = NULL; + + while (l1 && l2) + { + cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data); + + if (cmp <= 0) + { + l->next = l1; + l1 = l1->next; + } + else + { + l->next = l2; + l2 = l2->next; + } + l = l->next; + l->prev = lprev; + lprev = l; + } + l->next = l1 ? l1 : l2; + l->next->prev = l; + + return list.next; +} + +static GList* +g_list_sort_real (GList *list, + GFunc compare_func, + gpointer user_data) +{ + GList *l1, *l2; + + if (!list) + return NULL; + if (!list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) + { + if ((l2 = l2->next) == NULL) + break; + l1 = l1->next; + } + l2 = l1->next; + l1->next = NULL; + + return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data), + g_list_sort_real (l2, compare_func, user_data), + compare_func, + user_data); +} + +/** + * g_list_sort: + * @list: a #GList + * @compare_func: the comparison function used to sort the #GList. + * This function is passed the data from 2 elements of the #GList + * and should return 0 if they are equal, a negative value if the + * first element comes before the second, or a positive value if + * the first element comes after the second. + * + * Sorts a #GList using the given comparison function. + * + * Returns: the start of the sorted #GList + */ +/** + * GCompareFunc: + * @a: a value. + * @b: a value to compare with. + * @Returns: negative value if @a < @b; zero if @a = @b; positive + * value if @a > @b. + * + * Specifies the type of a comparison function used to compare two + * values. The function should return a negative integer if the first + * value comes before the second, 0 if they are equal, or a positive + * integer if the first value comes after the second. + **/ +GList * +g_list_sort (GList *list, + GCompareFunc compare_func) +{ + return g_list_sort_real (list, (GFunc) compare_func, NULL); + +} + +/** + * g_list_length: + * @list: a #GList + * + * Gets the number of elements in a #GList. + * + * + * This function iterates over the whole list to + * count its elements. + * + * + * Returns: the number of elements in the #GList + */ +guint +g_list_length (GList *list) +{ + guint length; + + length = 0; + while (list) + { + length++; + list = list->next; + } + + return length; +} + +/** + * g_list_foreach: + * @list: a #GList + * @func: the function to call with each element's data + * @user_data: user data to pass to the function + * + * Calls a function for each element of a #GList. + */ +/** + * GFunc: + * @data: the element's data. + * @user_data: user data passed to g_list_foreach() or + * g_slist_foreach(). + * + * Specifies the type of functions passed to g_list_foreach() and + * g_slist_foreach(). + **/ +void +g_list_foreach (GList *list, + GFunc func, + gpointer user_data) +{ + while (list) + { + GList *next = list->next; + (*func) (list->data, user_data); + list = next; + } +} + +/** + * g_list_free_full: + * @list: a pointer to a #GList + * @free_func: the function to be called to free each element's data + * + * Convenience method, which frees all the memory used by a #GList, and + * calls the specified destroy function on every element's data. + * + * Since: 2.28 + */ +void +g_list_free_full (GList *list, + GDestroyNotify free_func) +{ + g_list_foreach (list, (GFunc) free_func, NULL); + g_list_free (list); +} + +/** + * g_list_find_custom: + * @list: a #GList + * @data: user data passed to the function + * @func: the function to call for each element. + * It should return 0 when the desired element is found + * + * Finds an element in a #GList, using a supplied function to + * find the desired element. It iterates over the list, calling + * the given function which should return 0 when the desired + * element is found. The function takes two #gconstpointer arguments, + * the #GList element's data as the first argument and the + * given user data. + * + * Returns: the found #GList element, or %NULL if it is not found + */ +GList* +g_list_find_custom (GList *list, + gconstpointer data, + GCompareFunc func) +{ + g_return_val_if_fail (func != NULL, list); + + while (list) + { + if (! func (list->data, data)) + return list; + list = list->next; + } + + return NULL; +} diff --git a/glib-local/glist.h b/glib-local/glist.h new file mode 100644 index 0000000..47f2cfe --- /dev/null +++ b/glib-local/glist.h @@ -0,0 +1,56 @@ +#ifndef __G_LIST_H__ +#define __G_LIST_H__ + +typedef int gint; +typedef unsigned int guint; +typedef void* gpointer; +typedef const void *gconstpointer; +typedef gint (*GCompareFunc) (gconstpointer a, + gconstpointer b); +typedef gint (*GCompareDataFunc) (gconstpointer a, + gconstpointer b, + gpointer user_data); +typedef void (*GFunc) (gpointer data, + gpointer user_data); +typedef void (*GDestroyNotify) (gpointer data); + +struct _GList; +typedef struct _GList GList; + +struct _GList +{ + gpointer data; + GList *next; + GList *prev; +}; + +/* Doubly linked lists + */ +void g_list_free (GList *list); +GList* g_list_append (GList *list, + gpointer data); +GList* g_list_delete_link (GList *list, + GList *link_); +GList* g_list_first (GList *list); +GList* g_list_sort (GList *list, + GCompareFunc compare_func); +guint g_list_length (GList *list); +void g_list_foreach (GList *list, + GFunc func, + gpointer user_data); +void g_list_free_full (GList *list, + GDestroyNotify free_func); +GList* g_list_find_custom (GList *list, + gconstpointer data, + GCompareFunc func); + +#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL) +#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL) + +#define g_return_val_if_fail(expr,val) do { \ + if (expr) { } else \ + { \ + return (val); \ + } } while(0); + +#endif /* __G_LIST_H__ */