<commit_before>#include "ecore_private.h"
#include "Ecore.h"
#include "Ecore_Data.h"

/* Return information about the list */
static void *_ecore_list_current(Ecore_List * list);

/* Adding functions */
static int _ecore_list_insert(Ecore_List * list, Ecore_List_Node *node);
static int _ecore_list_append_0(Ecore_List * list, Ecore_List_Node *node);
static int _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node *node);

/* Remove functions */
static void *_ecore_list_remove_0(Ecore_List * list);
static void *_ecore_list_remove_first(Ecore_List * list);
static void *_ecore_list_remove_last(Ecore_List * list);

/* Basic traversal functions */
static void *_ecore_list_next(Ecore_List * list);
static void *_ecore_list_goto_last(Ecore_List * list);
static void *_ecore_list_goto_first(Ecore_List * list);
static void *_ecore_list_goto(Ecore_List * list, void *data);
static void *_ecore_list_goto_index(Ecore_List *list, int index);

/* Iterative function */
static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function,
                                void *user_data);
static void *_ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function,
                              const void *user_data);

/* Private double linked list functions */
static void *_ecore_dlist_previous(Ecore_DList * list);
static void *_ecore_dlist_remove_first(Ecore_DList *list);
static void *_ecore_dlist_goto_index(Ecore_DList *list, int index);

/* XXX: Begin deprecated code */
EAPI void *
_ecore_list2_append(void *in_list, void *in_item)
{
   Ecore_List2 *l, *new_l;
   Ecore_List2 *list, *item;

   list = in_list;
   item = in_item;
   new_l = item;
   new_l->next = NULL;
   if (!list)
     {
	new_l->prev = NULL;
	new_l->last = new_l;
	return new_l;
     }
   if (list->last) l = list->last;
   else for (l = list; l; l = l->next);
   l->next = new_l;
   new_l->prev = l;
   list->last = new_l;
   return list;
}

EAPI void *
_ecore_list2_prepend(void *in_list, void *in_item)
{
   Ecore_List2 *new_l;
   Ecore_List2 *list, *item;

   list = in_list;
   item = in_item;
   new_l = item;
   new_l->prev = NULL;
   if (!list)
     {
	new_l->next = NULL;
	new_l->last = new_l;
	return new_l;
     }
   new_l->next = list;
   list->prev = new_l;
   new_l->last = list->last;
   list->last = NULL;
   return new_l;
}

EAPI void *
_ecore_list2_append_relative(void *in_list, void *in_item, void *in_relative)
{
   Ecore_List2 *l;
   Ecore_List2 *list, *item, *relative;

   list = in_list;
   item = in_item;
   relative = in_relative;
   for (l = list; l; l = l->next)
     {
	if (l == relative)
	  {
	     Ecore_List2 *new_l;

	     new_l = item;
	     if (l->next)
	       {
		  new_l->next = l->next;
		  l->next->prev = new_l;
	       }

	     else new_l->next = NULL;
	     l->next = new_l;
	     new_l->prev = l;
	     if (!new_l->next)
	       list->last = new_l;
	     return list;
	  }
     }
   return _ecore_list2_append(list, item);
}

EAPI void *
_ecore_list2_prepend_relative(void *in_list, void *in_item, void *in_relative)
{
   Ecore_List2 *l;
   Ecore_List2 *list, *item, *relative;

   list = in_list;
   item = in_item;
   relative = in_relative;
   for (l = list; l; l = l->next)
     {
	if (l == relative)
	  {
	     Ecore_List2 *new_l;

	     new_l = item;
	     new_l->prev = l->prev;
	     new_l->next = l;
	     l->prev = new_l;
	     if (new_l->prev)
	       {
		  new_l->prev->next = new_l;
		  if (!new_l->next)
		    list->last = new_l;
		  return list;
	       }
	     else
	       {
		  if (!new_l->next)
		    new_l->last = new_l;
		  else
		    {
		       new_l->last = list->last;
		       list->last = NULL;
		    }
		  return new_l;
	       }
	  }
     }
   return _ecore_list2_prepend(list, item);
}

EAPI void *
_ecore_list2_remove(void *in_list, void *in_item)
{
   Ecore_List2 *return_l;
   Ecore_List2 *list, *item;

   /* checkme */
   if(!in_list)
     return in_list;

   list = in_list;
   item = in_item;
   if (!item) return list;
   if (item->next)
     item->next->prev = item->prev;
   if (item->prev)
     {
	item->prev->next = item->next;
	return_l = list;
     }
   else
     {
	return_l = item->next;
	if (return_l)
	  return_l->last = list->last;
     }
   if (item == list->last)
     list->last = item->prev;
   item->next = NULL;
   item->prev = NULL;
   return return_l;
}

EAPI void *
_ecore_list2_find(void *in_list, void *in_item)
{
   Ecore_List2 *l;
   Ecore_List2 *list, *item;

   list = in_list;
   item = in_item;
   for (l = list; l; l = l->next)
     {
	if (l == item) return item;
     }
   return NULL;
}
/* XXX: End deprecated code */

/**
@defgroup Ecore_Data_List_Creation_Group List Creation/Destruction Functions

Functions that create, initialize and destroy Ecore_Lists.
*/

/**
 * Create and initialize a new list.
 * @return  A new initialized list on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Creation_Group
 */
EAPI Ecore_List *
ecore_list_new()
{
   Ecore_List *list;

   list = (Ecore_List *)malloc(sizeof(Ecore_List));
   if (!list)
     return NULL;

   if (!ecore_list_init(list))
     {
	FREE(list);
	return NULL;
     }

   return list;
}

/**
 * Initialize a list to some sane starting values.
 * @param   list The list to initialize.
 * @return  @c TRUE if successful, @c FALSE if an error occurs.
 * @ingroup Ecore_Data_List_Creation_Group
 */
EAPI int 
ecore_list_init(Ecore_List *list)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   memset(list, 0, sizeof(Ecore_List));

   return TRUE;
}

/**
 * Free a list and all of it's nodes.
 * @param   list The list to be freed.
 * @ingroup Ecore_Data_List_Creation_Group
 */
EAPI void 
ecore_list_destroy(Ecore_List *list)
{
   void *data;

   CHECK_PARAM_POINTER("list", list);

   while (list->first)
     {
	data = _ecore_list_remove_first(list);
	if (list->free_func)
	  list->free_func(data);
     }

   FREE(list);
}

/**
 * Set the function for freeing data.
 * @param  list      The list that will use this function when nodes are
 *                   destroyed.
 * @param  free_func The function that will free the key data.
 * @return @c TRUE on successful set, @c FALSE otherwise.
 */
EAPI int 
ecore_list_set_free_cb(Ecore_List *list, Ecore_Free_Cb free_func)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   list->free_func = free_func;

   return TRUE;
}

/**
 * Checks the list for any nodes.
 * @param  list  The list to check for nodes
 * @return @c TRUE if no nodes in list, @c FALSE if the list contains nodes
 */
EAPI int 
ecore_list_is_empty(Ecore_List *list)
{
   int ret = TRUE;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   if (list->nodes)
     ret = FALSE;

   return ret;
}

/**
 * Returns the number of the current node.
 * @param  list The list to return the number of the current node.
 * @return The number of the current node in the list.
 */
EAPI int 
ecore_list_index(Ecore_List *list)
{
   int ret;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   ret = list->index;

   return ret;
}

/**
 * Find the number of nodes in the list.
 * @param  list The list to find the number of nodes
 * @return The number of nodes in the list.
 */
EAPI int 
ecore_list_nodes(Ecore_List *list)
{
   int ret = 0;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   ret = list->nodes;

   return ret;
}

/**
@defgroup Ecore_Data_List_Add_Item_Group List Item Adding Functions

Functions that are used to add nodes to an Ecore_List.
*/

/**
 * Append data to the list.
 * @param   list The list.
 * @param   data The data to append.
 * @return  @c FALSE if an error occurs, @c TRUE if appended successfully
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI inline int 
ecore_list_append(Ecore_List *list, void *data)
{
   int ret;
   Ecore_List_Node *node;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   node = ecore_list_node_new();
   node->data = data;

   ret = _ecore_list_append_0(list, node);

   return ret;
}

/* For adding items to the end of the list */
static int 
_ecore_list_append_0(Ecore_List *list, Ecore_List_Node *end)
{
   if (list->last)
     list->last->next = end;

   list->last = end;

   if (list->first == NULL)
     {
	list->first = end;
	list->index = 0;
	list->current = NULL;
     }

   if (list->index >= list->nodes)
     list->index++;

   list->nodes++;

   return TRUE;
}

/**
 * Prepend data to the beginning of the list.
 * @param  list The list.
 * @param  data The data to prepend.
 * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI inline int 
ecore_list_prepend(Ecore_List *list, void *data)
{
   int ret;
   Ecore_List_Node *node;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   node = ecore_list_node_new();
   node->data = data;

   ret = _ecore_list_prepend_0(list, node);

   return ret;
}

/* For adding items to the beginning of the list */
static int 
_ecore_list_prepend_0(Ecore_List *list, Ecore_List_Node *start)
{
   /* Put it at the beginning of the list */
   start->next = list->first;

   list->first = start;

   /* If no last node, then the first node is the last node */
   if (list->last == NULL)
     list->last = list->first;

   list->nodes++;
   list->index++;

   return TRUE;
}

/**
 * Insert data in front of the current point in the list.
 * @param   list The list to hold the inserted @p data.
 * @param   data The data to insert into @p list.
 * @return  @c FALSE if there is an error, @c TRUE on success
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI inline int 
ecore_list_insert(Ecore_List *list, void *data)
{
   int ret;
   Ecore_List_Node *node;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   node = ecore_list_node_new();
   node->data = data;

   ret = _ecore_list_insert(list, node);

   return ret;
}

/* For adding items in front of the current position in the list */
static int 
_ecore_list_insert(Ecore_List *list, Ecore_List_Node *new_node)
{
   /*
    * If the current point is at the beginning of the list, then it's the
    * same as prepending it to the list.
    */
   if (list->current == list->first)
     return _ecore_list_prepend_0(list, new_node);

   if (list->current == NULL)
     {
	int ret_value;

	ret_value = _ecore_list_append_0(list, new_node);
	list->current = list->last;

	return ret_value;
     }

   /* Setup the fields of the new node */
   new_node->next = list->current;

   /* And hook the node into the list */
   _ecore_list_goto_index(list, ecore_list_index(list) - 1);

   list->current->next = new_node;

   /* Now move the current item to the inserted item */
   list->current = new_node;
   list->nodes++;

   return TRUE;
}
/**
 * Append a list to the list.
 * @param   list The list.
 * @param   append The list to append.
 * @return  @c FALSE if an error occurs, @c TRUE if appended successfully
 * @ingroup Ecore_Data_List_Add_Item_Group
 */

EAPI int 
ecore_list_append_list(Ecore_List *list, Ecore_List *append)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
   CHECK_PARAM_POINTER_RETURN("append", append, FALSE);

   if (ecore_list_is_empty(append)) return TRUE;

   if (ecore_list_is_empty(list))
     {
	list->first = append->first;
	list->current = NULL;
	list->last = append->last;
	list->nodes = append->nodes;
     }
   else
     {
	list->last->next = append->first;
	list->last = append->last;
	list->nodes += append->nodes;
     }
   ecore_list_init(append);
   return TRUE;
}

/**
 * Prepend a list to the beginning of the list.
 * @param  list The list.
 * @param  prepend The list to prepend.
 * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI int 
ecore_list_prepend_list(Ecore_List *list, Ecore_List *prepend)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
   CHECK_PARAM_POINTER_RETURN("prepend", prepend, FALSE);

   if (ecore_list_is_empty(prepend)) return TRUE;

   if (ecore_list_is_empty(list))
     {
	list->first = prepend->first;
	list->current = NULL;
	list->last = prepend->last;
	list->nodes = prepend->nodes;
     }
   else
     {
	prepend->last->next = list->first;
	list->first = prepend->first;
	list->nodes += prepend->nodes;
	list->index += prepend->nodes;
     }
   ecore_list_init(prepend);
   return TRUE;
}

/**
@defgroup Ecore_Data_List_Remove_Item_Group List Item Removing Functions

Functions that remove nodes from an Ecore_List.
*/

/**
 * Remove the current item from the list.
 * @param   list The list to remove the current item
 * @return  A pointer to the removed data on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI inline void *
ecore_list_remove(Ecore_List *list)
{
   void *ret;

   CHECK_PARAM_POINTER_RETURN("list", list, NULL);

   ret = _ecore_list_remove_0(list);

   return ret;
}

/* Remove the current item from the list */
static void *
_ecore_list_remove_0(Ecore_List *list)
{
   void *ret = NULL;
   Ecore_List_Node *old;

   if (!list)
     return NULL;

   if (ecore_list_is_empty(list))
     return NULL;

   if (!list->current)
     return NULL;

   if (list->current == list->first)
     return _ecore_list_remove_first(list);

   if (list->current == list->last)
     return _ecore_list_remove_last(list);

   old = list->current;

   _ecore_list_goto_index(list, list->index - 1);

   list->current->next = old->next;
   old->next = NULL;
   ret = old->data;
   old->data = NULL;

   _ecore_list_next(list);

   ecore_list_node_destroy(old, NULL);
   list->nodes--;

   return ret;
}

/**
 * Remove and free the data in lists current position.
 * @param   list The list to remove and free the current item.
 * @return  @c TRUE on success, @c FALSE on error
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI int 
ecore_list_remove_destroy(Ecore_List *list)
{
   void *data;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   data = _ecore_list_remove_0(list);
   if (list->free_func)
     list->free_func(data);

   return TRUE;
}

/**
 * Remove the first item from the list.
 * @param   list The list to remove the current item
 * @return  Returns a pointer to the removed data on success, @c NULL on
 *          failure.
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI inline void *
ecore_list_remove_first(Ecore_List *list)
{
   void *ret;

   CHECK_PARAM_POINTER_RETURN("list", list, NULL);

   ret = _ecore_list_remove_first(list);

   return ret;
}

/* Remove the first item from the list */
static void *
_ecore_list_remove_first(Ecore_List *list)
{
   void *ret = NULL;
   Ecore_List_Node *old;

   if (!list)
     return NULL;

   if (ecore_list_is_empty(list))
     return NULL;

   old = list->first;

   list->first = list->first->next;

   if (list->current == old)
     list->current = list->first;
   else
     (list->index ? list->index-- : 0);

   if (list->last == old)
     list->last = list->first;

   ret = old->data;
   old->data = NULL;

   ecore_list_node_destroy(old, NULL);
   list->nodes--;

   return ret;
}

/**
 * Remove the last item from the list.
 * @param   list The list to remove the last node from
 * @return  A pointer to the removed data on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI inline void *
ecore_list_remove_last(Ecore_List *list)
{
   void *ret;

   CHECK_PARAM_POINTER_RETURN("list", list, NULL);

   ret = _ecore_list_remove_last(list);

   return ret;
}

/* Remove the last item from the list */
static void *
_ecore_list_remove_last(Ecore_List *list)
{
   void *ret = NULL;
   Ecore_List_Node *old, *prev;

   if (!list)
     return NULL;

   if (ecore_list_is_empty(list))
     return NULL;

   old = list->last;
   if (list->current == old)
     list->current = NULL;

   if (list->first == old)
     list->first = NULL;
   for (prev = list->first; prev && prev->next != old; prev = prev->next);
   list->last = prev;
   if (prev)
     {
	prev->next = NULL;
	if (list->current == old)
	  list->current = NULL;
     }

   if (old)
     {
	old->next = NULL;
	ret = old->data;
	old->data = NULL;
     }

   ecore_list_node_destroy(old, NULL);
   list->nodes--;

   return ret;
}

/**
@defgroup Ecore_Data_List_Traverse_Group List Traversal Functions

Functions that can be used to traverse an Ecore_List.
*/

/**
 * Make the current item the item with the given index number.
 * @param   list  The list.
 * @param   index The position to move the current item.
 * @return  A pointer to new current item on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Traverse_Group
 */
EAPI inline void *<commit_msg>Already did this test ~10 lines up.<commit_after>#include "ecore_private.h"
#include "Ecore.h"
#include "Ecore_Data.h"

/* Return information about the list */
static void *_ecore_list_current(Ecore_List * list);

/* Adding functions */
static int _ecore_list_insert(Ecore_List * list, Ecore_List_Node *node);
static int _ecore_list_append_0(Ecore_List * list, Ecore_List_Node *node);
static int _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node *node);

/* Remove functions */
static void *_ecore_list_remove_0(Ecore_List * list);
static void *_ecore_list_remove_first(Ecore_List * list);
static void *_ecore_list_remove_last(Ecore_List * list);

/* Basic traversal functions */
static void *_ecore_list_next(Ecore_List * list);
static void *_ecore_list_goto_last(Ecore_List * list);
static void *_ecore_list_goto_first(Ecore_List * list);
static void *_ecore_list_goto(Ecore_List * list, void *data);
static void *_ecore_list_goto_index(Ecore_List *list, int index);

/* Iterative function */
static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function,
                                void *user_data);
static void *_ecore_list_find(Ecore_List *list, Ecore_Compare_Cb function,
                              const void *user_data);

/* Private double linked list functions */
static void *_ecore_dlist_previous(Ecore_DList * list);
static void *_ecore_dlist_remove_first(Ecore_DList *list);
static void *_ecore_dlist_goto_index(Ecore_DList *list, int index);

/* XXX: Begin deprecated code */
EAPI void *
_ecore_list2_append(void *in_list, void *in_item)
{
   Ecore_List2 *l, *new_l;
   Ecore_List2 *list, *item;

   list = in_list;
   item = in_item;
   new_l = item;
   new_l->next = NULL;
   if (!list)
     {
	new_l->prev = NULL;
	new_l->last = new_l;
	return new_l;
     }
   if (list->last) l = list->last;
   else for (l = list; l; l = l->next);
   l->next = new_l;
   new_l->prev = l;
   list->last = new_l;
   return list;
}

EAPI void *
_ecore_list2_prepend(void *in_list, void *in_item)
{
   Ecore_List2 *new_l;
   Ecore_List2 *list, *item;

   list = in_list;
   item = in_item;
   new_l = item;
   new_l->prev = NULL;
   if (!list)
     {
	new_l->next = NULL;
	new_l->last = new_l;
	return new_l;
     }
   new_l->next = list;
   list->prev = new_l;
   new_l->last = list->last;
   list->last = NULL;
   return new_l;
}

EAPI void *
_ecore_list2_append_relative(void *in_list, void *in_item, void *in_relative)
{
   Ecore_List2 *l;
   Ecore_List2 *list, *item, *relative;

   list = in_list;
   item = in_item;
   relative = in_relative;
   for (l = list; l; l = l->next)
     {
	if (l == relative)
	  {
	     Ecore_List2 *new_l;

	     new_l = item;
	     if (l->next)
	       {
		  new_l->next = l->next;
		  l->next->prev = new_l;
	       }

	     else new_l->next = NULL;
	     l->next = new_l;
	     new_l->prev = l;
	     if (!new_l->next)
	       list->last = new_l;
	     return list;
	  }
     }
   return _ecore_list2_append(list, item);
}

EAPI void *
_ecore_list2_prepend_relative(void *in_list, void *in_item, void *in_relative)
{
   Ecore_List2 *l;
   Ecore_List2 *list, *item, *relative;

   list = in_list;
   item = in_item;
   relative = in_relative;
   for (l = list; l; l = l->next)
     {
	if (l == relative)
	  {
	     Ecore_List2 *new_l;

	     new_l = item;
	     new_l->prev = l->prev;
	     new_l->next = l;
	     l->prev = new_l;
	     if (new_l->prev)
	       {
		  new_l->prev->next = new_l;
		  if (!new_l->next)
		    list->last = new_l;
		  return list;
	       }
	     else
	       {
		  if (!new_l->next)
		    new_l->last = new_l;
		  else
		    {
		       new_l->last = list->last;
		       list->last = NULL;
		    }
		  return new_l;
	       }
	  }
     }
   return _ecore_list2_prepend(list, item);
}

EAPI void *
_ecore_list2_remove(void *in_list, void *in_item)
{
   Ecore_List2 *return_l;
   Ecore_List2 *list, *item;

   /* checkme */
   if(!in_list)
     return in_list;

   list = in_list;
   item = in_item;
   if (!item) return list;
   if (item->next)
     item->next->prev = item->prev;
   if (item->prev)
     {
	item->prev->next = item->next;
	return_l = list;
     }
   else
     {
	return_l = item->next;
	if (return_l)
	  return_l->last = list->last;
     }
   if (item == list->last)
     list->last = item->prev;
   item->next = NULL;
   item->prev = NULL;
   return return_l;
}

EAPI void *
_ecore_list2_find(void *in_list, void *in_item)
{
   Ecore_List2 *l;
   Ecore_List2 *list, *item;

   list = in_list;
   item = in_item;
   for (l = list; l; l = l->next)
     {
	if (l == item) return item;
     }
   return NULL;
}
/* XXX: End deprecated code */

/**
@defgroup Ecore_Data_List_Creation_Group List Creation/Destruction Functions

Functions that create, initialize and destroy Ecore_Lists.
*/

/**
 * Create and initialize a new list.
 * @return  A new initialized list on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Creation_Group
 */
EAPI Ecore_List *
ecore_list_new()
{
   Ecore_List *list;

   list = (Ecore_List *)malloc(sizeof(Ecore_List));
   if (!list)
     return NULL;

   if (!ecore_list_init(list))
     {
	FREE(list);
	return NULL;
     }

   return list;
}

/**
 * Initialize a list to some sane starting values.
 * @param   list The list to initialize.
 * @return  @c TRUE if successful, @c FALSE if an error occurs.
 * @ingroup Ecore_Data_List_Creation_Group
 */
EAPI int 
ecore_list_init(Ecore_List *list)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   memset(list, 0, sizeof(Ecore_List));

   return TRUE;
}

/**
 * Free a list and all of it's nodes.
 * @param   list The list to be freed.
 * @ingroup Ecore_Data_List_Creation_Group
 */
EAPI void 
ecore_list_destroy(Ecore_List *list)
{
   void *data;

   CHECK_PARAM_POINTER("list", list);

   while (list->first)
     {
	data = _ecore_list_remove_first(list);
	if (list->free_func)
	  list->free_func(data);
     }

   FREE(list);
}

/**
 * Set the function for freeing data.
 * @param  list      The list that will use this function when nodes are
 *                   destroyed.
 * @param  free_func The function that will free the key data.
 * @return @c TRUE on successful set, @c FALSE otherwise.
 */
EAPI int 
ecore_list_set_free_cb(Ecore_List *list, Ecore_Free_Cb free_func)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   list->free_func = free_func;

   return TRUE;
}

/**
 * Checks the list for any nodes.
 * @param  list  The list to check for nodes
 * @return @c TRUE if no nodes in list, @c FALSE if the list contains nodes
 */
EAPI int 
ecore_list_is_empty(Ecore_List *list)
{
   int ret = TRUE;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   if (list->nodes)
     ret = FALSE;

   return ret;
}

/**
 * Returns the number of the current node.
 * @param  list The list to return the number of the current node.
 * @return The number of the current node in the list.
 */
EAPI int 
ecore_list_index(Ecore_List *list)
{
   int ret;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   ret = list->index;

   return ret;
}

/**
 * Find the number of nodes in the list.
 * @param  list The list to find the number of nodes
 * @return The number of nodes in the list.
 */
EAPI int 
ecore_list_nodes(Ecore_List *list)
{
   int ret = 0;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   ret = list->nodes;

   return ret;
}

/**
@defgroup Ecore_Data_List_Add_Item_Group List Item Adding Functions

Functions that are used to add nodes to an Ecore_List.
*/

/**
 * Append data to the list.
 * @param   list The list.
 * @param   data The data to append.
 * @return  @c FALSE if an error occurs, @c TRUE if appended successfully
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI inline int 
ecore_list_append(Ecore_List *list, void *data)
{
   int ret;
   Ecore_List_Node *node;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   node = ecore_list_node_new();
   node->data = data;

   ret = _ecore_list_append_0(list, node);

   return ret;
}

/* For adding items to the end of the list */
static int 
_ecore_list_append_0(Ecore_List *list, Ecore_List_Node *end)
{
   if (list->last)
     list->last->next = end;

   list->last = end;

   if (list->first == NULL)
     {
	list->first = end;
	list->index = 0;
	list->current = NULL;
     }

   if (list->index >= list->nodes)
     list->index++;

   list->nodes++;

   return TRUE;
}

/**
 * Prepend data to the beginning of the list.
 * @param  list The list.
 * @param  data The data to prepend.
 * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI inline int 
ecore_list_prepend(Ecore_List *list, void *data)
{
   int ret;
   Ecore_List_Node *node;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   node = ecore_list_node_new();
   node->data = data;

   ret = _ecore_list_prepend_0(list, node);

   return ret;
}

/* For adding items to the beginning of the list */
static int 
_ecore_list_prepend_0(Ecore_List *list, Ecore_List_Node *start)
{
   /* Put it at the beginning of the list */
   start->next = list->first;

   list->first = start;

   /* If no last node, then the first node is the last node */
   if (list->last == NULL)
     list->last = list->first;

   list->nodes++;
   list->index++;

   return TRUE;
}

/**
 * Insert data in front of the current point in the list.
 * @param   list The list to hold the inserted @p data.
 * @param   data The data to insert into @p list.
 * @return  @c FALSE if there is an error, @c TRUE on success
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI inline int 
ecore_list_insert(Ecore_List *list, void *data)
{
   int ret;
   Ecore_List_Node *node;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   node = ecore_list_node_new();
   node->data = data;

   ret = _ecore_list_insert(list, node);

   return ret;
}

/* For adding items in front of the current position in the list */
static int 
_ecore_list_insert(Ecore_List *list, Ecore_List_Node *new_node)
{
   /*
    * If the current point is at the beginning of the list, then it's the
    * same as prepending it to the list.
    */
   if (list->current == list->first)
     return _ecore_list_prepend_0(list, new_node);

   if (list->current == NULL)
     {
	int ret_value;

	ret_value = _ecore_list_append_0(list, new_node);
	list->current = list->last;

	return ret_value;
     }

   /* Setup the fields of the new node */
   new_node->next = list->current;

   /* And hook the node into the list */
   _ecore_list_goto_index(list, ecore_list_index(list) - 1);

   list->current->next = new_node;

   /* Now move the current item to the inserted item */
   list->current = new_node;
   list->nodes++;

   return TRUE;
}
/**
 * Append a list to the list.
 * @param   list The list.
 * @param   append The list to append.
 * @return  @c FALSE if an error occurs, @c TRUE if appended successfully
 * @ingroup Ecore_Data_List_Add_Item_Group
 */

EAPI int 
ecore_list_append_list(Ecore_List *list, Ecore_List *append)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
   CHECK_PARAM_POINTER_RETURN("append", append, FALSE);

   if (ecore_list_is_empty(append)) return TRUE;

   if (ecore_list_is_empty(list))
     {
	list->first = append->first;
	list->current = NULL;
	list->last = append->last;
	list->nodes = append->nodes;
     }
   else
     {
	list->last->next = append->first;
	list->last = append->last;
	list->nodes += append->nodes;
     }
   ecore_list_init(append);
   return TRUE;
}

/**
 * Prepend a list to the beginning of the list.
 * @param  list The list.
 * @param  prepend The list to prepend.
 * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
 * @ingroup Ecore_Data_List_Add_Item_Group
 */
EAPI int 
ecore_list_prepend_list(Ecore_List *list, Ecore_List *prepend)
{
   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
   CHECK_PARAM_POINTER_RETURN("prepend", prepend, FALSE);

   if (ecore_list_is_empty(prepend)) return TRUE;

   if (ecore_list_is_empty(list))
     {
	list->first = prepend->first;
	list->current = NULL;
	list->last = prepend->last;
	list->nodes = prepend->nodes;
     }
   else
     {
	prepend->last->next = list->first;
	list->first = prepend->first;
	list->nodes += prepend->nodes;
	list->index += prepend->nodes;
     }
   ecore_list_init(prepend);
   return TRUE;
}

/**
@defgroup Ecore_Data_List_Remove_Item_Group List Item Removing Functions

Functions that remove nodes from an Ecore_List.
*/

/**
 * Remove the current item from the list.
 * @param   list The list to remove the current item
 * @return  A pointer to the removed data on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI inline void *
ecore_list_remove(Ecore_List *list)
{
   void *ret;

   CHECK_PARAM_POINTER_RETURN("list", list, NULL);

   ret = _ecore_list_remove_0(list);

   return ret;
}

/* Remove the current item from the list */
static void *
_ecore_list_remove_0(Ecore_List *list)
{
   void *ret = NULL;
   Ecore_List_Node *old;

   if (!list)
     return NULL;

   if (ecore_list_is_empty(list))
     return NULL;

   if (!list->current)
     return NULL;

   if (list->current == list->first)
     return _ecore_list_remove_first(list);

   if (list->current == list->last)
     return _ecore_list_remove_last(list);

   old = list->current;

   _ecore_list_goto_index(list, list->index - 1);

   list->current->next = old->next;
   old->next = NULL;
   ret = old->data;
   old->data = NULL;

   _ecore_list_next(list);

   ecore_list_node_destroy(old, NULL);
   list->nodes--;

   return ret;
}

/**
 * Remove and free the data in lists current position.
 * @param   list The list to remove and free the current item.
 * @return  @c TRUE on success, @c FALSE on error
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI int 
ecore_list_remove_destroy(Ecore_List *list)
{
   void *data;

   CHECK_PARAM_POINTER_RETURN("list", list, FALSE);

   data = _ecore_list_remove_0(list);
   if (list->free_func)
     list->free_func(data);

   return TRUE;
}

/**
 * Remove the first item from the list.
 * @param   list The list to remove the current item
 * @return  Returns a pointer to the removed data on success, @c NULL on
 *          failure.
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI inline void *
ecore_list_remove_first(Ecore_List *list)
{
   void *ret;

   CHECK_PARAM_POINTER_RETURN("list", list, NULL);

   ret = _ecore_list_remove_first(list);

   return ret;
}

/* Remove the first item from the list */
static void *
_ecore_list_remove_first(Ecore_List *list)
{
   void *ret = NULL;
   Ecore_List_Node *old;

   if (!list)
     return NULL;

   if (ecore_list_is_empty(list))
     return NULL;

   old = list->first;

   list->first = list->first->next;

   if (list->current == old)
     list->current = list->first;
   else
     (list->index ? list->index-- : 0);

   if (list->last == old)
     list->last = list->first;

   ret = old->data;
   old->data = NULL;

   ecore_list_node_destroy(old, NULL);
   list->nodes--;

   return ret;
}

/**
 * Remove the last item from the list.
 * @param   list The list to remove the last node from
 * @return  A pointer to the removed data on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Remove_Item_Group
 */
EAPI inline void *
ecore_list_remove_last(Ecore_List *list)
{
   void *ret;

   CHECK_PARAM_POINTER_RETURN("list", list, NULL);

   ret = _ecore_list_remove_last(list);

   return ret;
}

/* Remove the last item from the list */
static void *
_ecore_list_remove_last(Ecore_List *list)
{
   void *ret = NULL;
   Ecore_List_Node *old, *prev;

   if (!list)
     return NULL;

   if (ecore_list_is_empty(list))
     return NULL;

   old = list->last;
   if (list->current == old)
     list->current = NULL;

   if (list->first == old)
     list->first = NULL;
   for (prev = list->first; prev && prev->next != old; prev = prev->next);
   list->last = prev;
   if (prev)
     prev->next = NULL;

   if (old)
     {
	old->next = NULL;
	ret = old->data;
	old->data = NULL;
     }

   ecore_list_node_destroy(old, NULL);
   list->nodes--;

   return ret;
}

/**
@defgroup Ecore_Data_List_Traverse_Group List Traversal Functions

Functions that can be used to traverse an Ecore_List.
*/

/**
 * Make the current item the item with the given index number.
 * @param   list  The list.
 * @param   index The position to move the current item.
 * @return  A pointer to new current item on success, @c NULL on failure.
 * @ingroup Ecore_Data_List_Traverse_Group
 */
EAPI inline void *
{'fraction_non_alphanumeric': 0.11715683314209795, 'fraction_numerical': 0.0024759949272299053, 'mean_word_length': 3.13522287426645, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 359, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '744028', 'n_tokens_mistral': 12197, 'n_tokens_neox': 11805, 'n_words': 3277}