Blame synfig-osx/launcher/x-list.c

Carlos Lopez a09598
/* x-list.c
Carlos Lopez a09598
   $Id: x-list.c,v 1.16 2003/07/18 00:52:19 jharper Exp $
Carlos Lopez a09598
Carlos Lopez a09598
   Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
Carlos Lopez a09598
Carlos Lopez a09598
   Permission is hereby granted, free of charge, to any person
Carlos Lopez a09598
   obtaining a copy of this software and associated documentation files
Carlos Lopez a09598
   (the "Software"), to deal in the Software without restriction,
Carlos Lopez a09598
   including without limitation the rights to use, copy, modify, merge,
Carlos Lopez a09598
   publish, distribute, sublicense, and/or sell copies of the Software,
Carlos Lopez a09598
   and to permit persons to whom the Software is furnished to do so,
Carlos Lopez a09598
   subject to the following conditions:
Carlos Lopez a09598
Carlos Lopez a09598
   The above copyright notice and this permission notice shall be
Carlos Lopez a09598
   included in all copies or substantial portions of the Software.
Carlos Lopez a09598
Carlos Lopez a09598
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Carlos Lopez a09598
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Carlos Lopez a09598
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Carlos Lopez a09598
   NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
Carlos Lopez a09598
   HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
Carlos Lopez a09598
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Carlos Lopez a09598
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Carlos Lopez a09598
   DEALINGS IN THE SOFTWARE.
Carlos Lopez a09598
Carlos Lopez a09598
   Except as contained in this notice, the name(s) of the above
Carlos Lopez a09598
   copyright holders shall not be used in advertising or otherwise to
Carlos Lopez a09598
   promote the sale, use or other dealings in this Software without
Carlos Lopez a09598
   prior written authorization. */
Carlos Lopez a09598
Carlos Lopez a09598
#include "x-list.h"
Carlos Lopez a09598
#include <stdlib.h></stdlib.h>
Carlos Lopez a09598
#include <assert.h></assert.h>
Carlos Lopez a09598
#include <pthread.h></pthread.h>
Carlos Lopez a09598
Carlos Lopez a09598
/* Allocate in ~4k blocks */
Carlos Lopez a09598
#define NODES_PER_BLOCK 508
Carlos Lopez a09598
Carlos Lopez a09598
typedef struct x_list_block_struct x_list_block;
Carlos Lopez a09598
Carlos Lopez a09598
struct x_list_block_struct {
Carlos Lopez a09598
    x_list l[NODES_PER_BLOCK];
Carlos Lopez a09598
};
Carlos Lopez a09598
Carlos Lopez a09598
static x_list *freelist;
Carlos Lopez a09598
Carlos Lopez a09598
static pthread_mutex_t freelist_lock = PTHREAD_MUTEX_INITIALIZER;
Carlos Lopez a09598
Carlos Lopez a09598
static inline void
Carlos Lopez a09598
list_free_1 (x_list *node)
Carlos Lopez a09598
{
Carlos Lopez a09598
    node->next = freelist;
Carlos Lopez a09598
    freelist = node;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN void
Carlos Lopez a09598
X_PFX (list_free_1) (x_list *node)
Carlos Lopez a09598
{
Carlos Lopez a09598
    assert (node != NULL);
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_mutex_lock (&freelist_lock);
Carlos Lopez a09598
Carlos Lopez a09598
    list_free_1 (node);
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_mutex_unlock (&freelist_lock);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN void
Carlos Lopez a09598
X_PFX (list_free) (x_list *lst)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *next;
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_mutex_lock (&freelist_lock);
Carlos Lopez a09598
Carlos Lopez a09598
    for (; lst != NULL; lst = next)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	next = lst->next;
Carlos Lopez a09598
	list_free_1 (lst);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_mutex_unlock (&freelist_lock);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_prepend) (x_list *lst, void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *node;
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_mutex_lock (&freelist_lock);
Carlos Lopez a09598
Carlos Lopez a09598
    if (freelist == NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	x_list_block *b;
Carlos Lopez a09598
	int i;
Carlos Lopez a09598
Carlos Lopez a09598
	b = malloc (sizeof (x_list_block));
Carlos Lopez a09598
Carlos Lopez a09598
	for (i = 0; i < NODES_PER_BLOCK - 1; i++)
Carlos Lopez a09598
	    b->l[i].next = &(b->l[i+1]);
Carlos Lopez a09598
	b->l[i].next = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
	freelist = b->l;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    node = freelist;
Carlos Lopez a09598
    freelist = node->next;
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_mutex_unlock (&freelist_lock);
Carlos Lopez a09598
Carlos Lopez a09598
    node->next = lst;
Carlos Lopez a09598
    node->data = data;
Carlos Lopez a09598
Carlos Lopez a09598
    return node;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_append) (x_list *lst, void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *head = lst;
Carlos Lopez a09598
Carlos Lopez a09598
    if (lst == NULL)
Carlos Lopez a09598
	return X_PFX (list_prepend) (NULL, data);
Carlos Lopez a09598
Carlos Lopez a09598
    while (lst->next != NULL)
Carlos Lopez a09598
	lst = lst->next;
Carlos Lopez a09598
Carlos Lopez a09598
    lst->next = X_PFX (list_prepend) (NULL, data);
Carlos Lopez a09598
Carlos Lopez a09598
    return head;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_reverse) (x_list *lst)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *head = NULL, *next;
Carlos Lopez a09598
    
Carlos Lopez a09598
    while (lst != NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	next = lst->next;
Carlos Lopez a09598
	lst->next = head;
Carlos Lopez a09598
	head = lst;
Carlos Lopez a09598
	lst = next;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return head;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_find) (x_list *lst, void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    for (; lst != NULL; lst = lst->next)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	if (lst->data == data)
Carlos Lopez a09598
	    return lst;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return NULL;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_nth) (x_list *lst, int n)
Carlos Lopez a09598
{
Carlos Lopez a09598
    while (n-- > 0 && lst != NULL)
Carlos Lopez a09598
	lst = lst->next;
Carlos Lopez a09598
Carlos Lopez a09598
    return lst;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_pop) (x_list *lst, void **data_ret)
Carlos Lopez a09598
{
Carlos Lopez a09598
    void *data = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
    if (lst != NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	x_list *tem = lst;
Carlos Lopez a09598
	data = lst->data;
Carlos Lopez a09598
	lst = lst->next;
Carlos Lopez a09598
	X_PFX (list_free_1) (tem);
Carlos Lopez a09598
    }
Carlos Lopez a09598
	
Carlos Lopez a09598
    if (data_ret != NULL)
Carlos Lopez a09598
	*data_ret = data;
Carlos Lopez a09598
Carlos Lopez a09598
    return lst;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_filter) (x_list *lst,
Carlos Lopez a09598
		     int (*pred) (void *item, void *data), void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *ret = NULL, *node;
Carlos Lopez a09598
Carlos Lopez a09598
    for (node = lst; node != NULL; node = node->next)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	if ((*pred) (node->data, data))
Carlos Lopez a09598
	    ret = X_PFX (list_prepend) (ret, node->data);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return X_PFX (list_reverse) (ret);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_map) (x_list *lst,
Carlos Lopez a09598
		  void *(*fun) (void *item, void *data), void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *ret = NULL, *node;
Carlos Lopez a09598
Carlos Lopez a09598
    for (node = lst; node != NULL; node = node->next)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	X_PFX (list_prepend) (ret, fun (node->data, data));
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return X_PFX (list_reverse) (ret);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_copy) (x_list *lst)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *copy = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
    for (; lst != NULL; lst = lst->next)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	copy = X_PFX (list_prepend) (copy, lst->data);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return X_PFX (list_reverse) (copy);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_remove) (x_list *lst, void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list **ptr, *node;
Carlos Lopez a09598
Carlos Lopez a09598
    for (ptr = &lst; *ptr != NULL;)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	node = *ptr;
Carlos Lopez a09598
Carlos Lopez a09598
	if (node->data == data)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    *ptr = node->next;
Carlos Lopez a09598
	    X_PFX (list_free_1) (node);
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else
Carlos Lopez a09598
	    ptr = &((*ptr)->next);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return lst;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN unsigned int
Carlos Lopez a09598
X_PFX (list_length) (x_list *lst)
Carlos Lopez a09598
{
Carlos Lopez a09598
    unsigned int n;
Carlos Lopez a09598
Carlos Lopez a09598
    n = 0;
Carlos Lopez a09598
    for (; lst != NULL; lst = lst->next)
Carlos Lopez a09598
	n++;
Carlos Lopez a09598
Carlos Lopez a09598
    return n;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN void
Carlos Lopez a09598
X_PFX (list_foreach) (x_list *lst,
Carlos Lopez a09598
		      void (*fun) (void *data, void *user_data),
Carlos Lopez a09598
		      void *user_data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    for (; lst != NULL; lst = lst->next)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	(*fun) (lst->data, user_data);
Carlos Lopez a09598
    }
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static x_list *
Carlos Lopez a09598
list_sort_1 (x_list *lst, int length,
Carlos Lopez a09598
	     int (*less) (const void *, const void *))
Carlos Lopez a09598
{
Carlos Lopez a09598
    x_list *mid, *ptr;
Carlos Lopez a09598
    x_list *out_head, *out;
Carlos Lopez a09598
    int mid_point, i;
Carlos Lopez a09598
Carlos Lopez a09598
    /* This is a standard (stable) list merge sort */
Carlos Lopez a09598
Carlos Lopez a09598
    if (length < 2)
Carlos Lopez a09598
	return lst;
Carlos Lopez a09598
Carlos Lopez a09598
    /* Calculate the halfway point. Split the list into two sub-lists. */
Carlos Lopez a09598
Carlos Lopez a09598
    mid_point = length / 2;
Carlos Lopez a09598
    ptr = lst;
Carlos Lopez a09598
    for (i = mid_point - 1; i > 0; i--)
Carlos Lopez a09598
        ptr = ptr->next;
Carlos Lopez a09598
    mid = ptr->next;
Carlos Lopez a09598
    ptr->next = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
    /* Sort each sub-list. */
Carlos Lopez a09598
Carlos Lopez a09598
    lst = list_sort_1 (lst, mid_point, less);
Carlos Lopez a09598
    mid = list_sort_1 (mid, length - mid_point, less);
Carlos Lopez a09598
Carlos Lopez a09598
    /* Then merge them back together. */
Carlos Lopez a09598
Carlos Lopez a09598
    assert (lst != NULL && mid != NULL);
Carlos Lopez a09598
Carlos Lopez a09598
    if ((*less) (mid->data, lst->data))
Carlos Lopez a09598
	out = out_head = mid, mid = mid->next;
Carlos Lopez a09598
    else
Carlos Lopez a09598
	out = out_head = lst, lst = lst->next;
Carlos Lopez a09598
Carlos Lopez a09598
    while (lst != NULL && mid != NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
        if ((*less) (mid->data, lst->data))
Carlos Lopez a09598
	    out = out->next = mid, mid = mid->next;
Carlos Lopez a09598
        else
Carlos Lopez a09598
	    out = out->next = lst, lst = lst->next;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (lst != NULL)
Carlos Lopez a09598
        out->next = lst;
Carlos Lopez a09598
    else
Carlos Lopez a09598
        out->next = mid;
Carlos Lopez a09598
Carlos Lopez a09598
    return out_head;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
X_EXTERN x_list *
Carlos Lopez a09598
X_PFX (list_sort) (x_list *lst, int (*less) (const void *, const void *))
Carlos Lopez a09598
{
Carlos Lopez a09598
    int length;
Carlos Lopez a09598
Carlos Lopez a09598
    length = X_PFX (list_length) (lst);
Carlos Lopez a09598
Carlos Lopez a09598
    return list_sort_1 (lst, length, less);
Carlos Lopez a09598
}