GophHub - kevinboone/epub2txt2/src/list.c


Raw File

    1	/*============================================================================
    2	  epub2txt v2 
    3	  list.c
    4	  Copyright (c)2000-2020 Kevin Boone, GPL v3.0
    5	============================================================================*/
    6	
    7	
    8	#include <stdio.h>
    9	#include <stdlib.h>
   10	#include <memory.h>
   11	
   12	#if !defined(__MACH__)
   13	#include <malloc.h>
   14	#endif
   15	
   16	#include <pthread.h>
   17	#include "list.h" 
   18	
   19	typedef struct _ListItem
   20	  {
   21	  struct _ListItem *next;
   22	  void *data;
   23	  } ListItem;
   24	
   25	struct _List
   26	  {
   27	  pthread_mutex_t mutex;
   28	  ListItemFreeFn free_fn; 
   29	  ListItem *head;
   30	  };
   31	
   32	/*==========================================================================
   33	list_create
   34	*==========================================================================*/
   35	List *list_create (ListItemFreeFn free_fn)
   36	  {
   37	  List *list = malloc (sizeof (List));
   38	  memset (list, 0, sizeof (List));
   39	  list->free_fn = free_fn;
   40	  pthread_mutex_init (&list->mutex, NULL);
   41	  return list;
   42	  }
   43	
   44	/*==========================================================================
   45	list_create_strings 
   46	*==========================================================================*/
   47	List *list_create_strings (void)
   48	  {
   49	  return list_create (free);
   50	  }
   51	
   52	/*==========================================================================
   53	list_destroy
   54	*==========================================================================*/
   55	void list_destroy (List *self)
   56	  {
   57	  if (!self) return;
   58	
   59	  pthread_mutex_lock (&self->mutex);
   60	  ListItem *l = self->head;
   61	  while (l)
   62	    {
   63	    if (self->free_fn)
   64	      self->free_fn (l->data);
   65	    ListItem *temp = l;
   66	    l = l->next;
   67	    free (temp);
   68	    }
   69	
   70	  pthread_mutex_unlock (&self->mutex);
   71	  pthread_mutex_destroy (&self->mutex);
   72	  free (self);
   73	  }
   74	
   75	
   76	/*==========================================================================
   77	list_prepend
   78	Note that the caller must not modify or free the item added to the list. It
   79	will remain on the list until free'd by the list itself, by calling
   80	the supplied free function
   81	*==========================================================================*/
   82	void list_prepend (List *self, void *item)
   83	  {
   84	  pthread_mutex_lock (&self->mutex);
   85	  ListItem *i = malloc (sizeof (ListItem));
   86	  i->data = item;
   87	  i->next = NULL;
   88	
   89	  if (self->head)
   90	    {
   91	    i->next = self->head;
   92	    self->head = i;
   93	    }
   94	  else
   95	    {
   96	    self->head = i;
   97	    }
   98	  pthread_mutex_unlock (&self->mutex);
   99	  }
  100	
  101	
  102	/*==========================================================================
  103	list_append
  104	Note that the caller must not modify or free the item added to the list. It
  105	will remain on the list until free'd by the list itself, by calling
  106	the supplied free function
  107	*==========================================================================*/
  108	void list_append (List *self, void *item)
  109	  {
  110	  pthread_mutex_lock (&self->mutex);
  111	  ListItem *i = malloc (sizeof (ListItem));
  112	  i->data = item;
  113	  i->next = NULL;
  114	
  115	  if (self->head)
  116	    {
  117	    ListItem *l = self->head;
  118	    while (l->next)
  119	      l = l->next;
  120	    l->next = i;
  121	    }
  122	  else
  123	    {
  124	    self->head = i;
  125	    }
  126	  pthread_mutex_unlock (&self->mutex);
  127	  }
  128	
  129	
  130	/*==========================================================================
  131	list_length
  132	*==========================================================================*/
  133	int list_length (List *self)
  134	  {
  135	  if (!self) return 0;
  136	
  137	  pthread_mutex_lock (&self->mutex);
  138	  ListItem *l = self->head;
  139	  int i = 0;
  140	  while (l != NULL)
  141	    {
  142	    l = l->next;
  143	    i++;
  144	    }
  145	
  146	  pthread_mutex_unlock (&self->mutex);
  147	  return i;
  148	  }
  149	
  150	/*==========================================================================
  151	list_get
  152	*==========================================================================*/
  153	void *list_get (List *self, int index)
  154	  {
  155	  if (!self) return NULL;
  156	
  157	  pthread_mutex_lock (&self->mutex);
  158	  ListItem *l = self->head;
  159	  int i = 0;
  160	  while (l != NULL && i != index)
  161	    {
  162	    l = l->next;
  163	    i++;
  164	    }
  165	  pthread_mutex_unlock (&self->mutex);
  166	
  167	  return l->data;
  168	  }
  169	
  170	
  171	/*==========================================================================
  172	list_dump
  173	*==========================================================================*/
  174	void list_dump (List *self)
  175	  {
  176	  int i, l = list_length (self);
  177	  for (i = 0; i < l; i++)
  178	    {
  179	    const char *s = list_get (self, i);
  180	    printf ("%s\n", s);
  181	    }
  182	  }
  183	
  184	
  185	/*==========================================================================
  186	list_contains
  187	*==========================================================================*/
  188	BOOL list_contains (List *self, const void *item, ListCompareFn fn)
  189	  {
  190	  if (!self) return FALSE;
  191	  pthread_mutex_lock (&self->mutex);
  192	  ListItem *l = self->head;
  193	  BOOL found = FALSE;
  194	  while (l != NULL && !found)
  195	    {
  196	    if (fn (l->data, item) == 0) found = TRUE; 
  197	    l = l->next;
  198	    }
  199	  pthread_mutex_unlock (&self->mutex);
  200	  return found; 
  201	  }
  202	
  203	
  204	/*==========================================================================
  205	list_contains_string
  206	*==========================================================================*/
  207	BOOL list_contains_string (List *self, const char *item)
  208	  {
  209	  return list_contains (self, item, (ListCompareFn)strcmp);
  210	  }
  211	
  212	
  213	/*==========================================================================
  214	list_remove
  215	IMPORTANT -- The "item" argument cannot be a direct reference to an
  216	item already in the list. If that items is removed from the list its
  217	memory will be freed. The "item" argument will this be an invalid
  218	memory reference, and the program will crash. It is necessary
  219	to copy the item first.
  220	*==========================================================================*/
  221	void list_remove (List *self, const void *item, ListCompareFn fn)
  222	  {
  223	  if (!self) return;
  224	  pthread_mutex_lock (&self->mutex);
  225	  ListItem *l = self->head;
  226	  ListItem *last_good = NULL;
  227	  while (l != NULL)
  228	    {
  229	    if (fn (l->data, item) == 0)
  230	      {
  231	      if (l == self->head)
  232	        {
  233	        self->head = l->next; // l-> next might be null
  234	        }
  235	      else
  236	        {
  237	        if (last_good) last_good->next = l->next;
  238	        }
  239	      self->free_fn (l->data);  
  240	      ListItem *temp = l->next;
  241	      free (l);
  242	      l = temp;
  243	      } 
  244	    else
  245	      {
  246	      last_good = l;
  247	      l = l->next;
  248	      }
  249	    }
  250	  pthread_mutex_unlock (&self->mutex);
  251	  }
  252	
  253	/*==========================================================================
  254	list_remove_string
  255	*==========================================================================*/
  256	void list_remove_string (List *self, const char *item)
  257	  {
  258	  list_remove (self, item, (ListCompareFn)strcmp);
  259	  }
  260	
  261	
  262	/*==========================================================================
  263	list_clone
  264	*==========================================================================*/
  265	List *list_clone (List *self, ListCopyFn copyFn)
  266	  {
  267	  ListItemFreeFn free_fn = self->free_fn; 
  268	  List *new = list_create (free_fn);
  269	
  270	  pthread_mutex_lock (&self->mutex);
  271	  ListItem *l = self->head;
  272	  while (l != NULL)
  273	    {
  274	    void *data = copyFn (l->data);
  275	    list_append (new, data);
  276	    l = l->next;
  277	    }
  278	  pthread_mutex_unlock (&self->mutex);
  279	
  280	  return new;
  281	  }
  282	
  283	
  284	
  285	

Generated by GNU Enscript 1.6.6, and GophHub 1.3.