[SRC-C99] Listas doblemente enlazadas (varias funciones).

Iniciado por BlackZeroX, 15 Enero 2013, 07:01 AM

0 Miembros y 1 Visitante están viendo este tema.

BlackZeroX

Son varias funciones para tratar a las listas, Absténganse de entregar a sus maestros este código si no lo llegan a comprender lo "básico". NO INCLUÍ las funciones de ordenamiento debido a que tienen un problema, seguro se me paso alguno... igual no es nada del otro mundo (fue cuando incluí la macro LIST_INTEGRAL_RELATIONSHIP).

list.h

#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED

/** \autor Ortega Avila Miguel Angel (BlackZeroX).
*
* \website http://infrnagelux.sytes.net/
* \copileft El presente código se da de manera gratuita sin ningún derecho a venta.
* \note muchas de las funciones aqui presentadas "inútiles" como:
* list_before()
* list_after()
* list_getlist()
* Note que esta ultima solo esta activa mientras este declarada la macro.
*
* http://foro.elhacker.net/programacion_cc/srcc99_para_que_dejen_de_preguntar_por_las_listas-t380839.0.html
*
*/

#include <stdbool.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>

#ifndef LIST_INTEGRAL_RELATIONSHIP
/** \brief Al declarar LIST_INTEGRAL_RELATIONSHIP se reduce considerablemente la velocidad
* en el proceso list_sort() debido a que se actualizan TODOS los miembros list de la estructura
* struct list_item de cada elemento; De igual manera aumenta la seguridad de no eliminar o hacer
* operaciones indebidas entre elementos.
*
*/
///#define LIST_INTEGRAL_RELATIONSHIP /**< Comentar/descomentar */
#endif

#define LIST_SIZE_ITEM sizeof(struct list_item)

struct list;
typedef void*               list_value_t; ///typedef uintptr_t            list_value_t;
typedef struct list*        list_t;

/** \brief Definición callback que se encarga de crear un duplicado de un elemento de lista.
* \param item: Valor a duplicar.
*
* \return Retorna el elemento list_value_t duplicado del parámetro value.
*
*/
typedef list_value_t (*list_callback_clone_item)
(const list_value_t value);

/** \brief Definición de callback que se encarga de destruir la memoria asignada al list_value_t.
*
* \param item: Puntero a la estructura que se le pretende liberar su valor asignado debe liberarse solo el miembro value.
*
*/
typedef
void(*list_callback_release_item)
(const list_value_t value);

/** \brief Definición de callback que se encarga comparar dos list_value_t.
*
* \param value1: list_value_t que se comparara con value2.
* \param value2: list_value_t que se comparara con value1.
* \return Retorna el resultado de la comparación.
* LIST_CMP_LESS_THAT: Si value1 < value2.
* LIST_CMP_EQUAL: Si value1 == value2.
* LIST_CMP_GREATER_THAT: Si value1 > value2.
*
*/
typedef
enum list_cmp(*list_callback_compare_item)
(const list_value_t value1,
const list_value_t value2);

enum list_cmp {
   LIST_CMP_EQUAL          = 1,    /**< */
   LIST_CMP_LESS_THAT      = 2,    /**< */
   LIST_CMP_GREATER_THAT   = 4     /**< */
};

enum list_sort {
   LIST_SORT_ASC,  /**< */
   LIST_SORT_DESC  /**< */
};

struct list_item {
   list_value_t        value;  /**< Valor del item actual. */
   struct list_item    *prev;  /**< Apuntador al item derecho. */
   struct list_item    *next;  /**< Apuntador al item izquierdo. */
   #ifdef LIST_INTEGRAL_RELATIONSHIP
   list_t              list;   /**< Apuntador a los datos generales de la lista. */
   #endif
};


struct list {                       /**< Estructura que guarda la información generalizada de una lista de datos */
   struct list_item    *first;     /**< Primer elemento agregado a la lista */
   struct list_item    *last;      /**< Ultimo elemento agregado a la lista */
   #ifdef LIST_INTEGRAL_RELATIONSHIP
   size_t              size;       /**< Cantidad de elementos */
   #endif
   list_callback_clone_item    clone_item;     /**< Puntero a la función callback que realiza las acciones CLONE, RELEASE y COMPARE */
   list_callback_release_item  release_item;   /**< Puntero a la función callback que realiza las acciones CLONE, RELEASE y COMPARE */
   list_callback_compare_item  compare_item;   /**< Puntero a la función callback que realiza las acciones CLONE, RELEASE y COMPARE */
};

/** \brief Obtiene el item siguiente al inicado.
*
* \param item: Item pivote en la lista.
* \return Retorna el struct list_item * siguiente al indicado; NULL si no hay ningun item.
*
*/
struct list_item*
list_after(struct list_item *item);

/** \brief Crea una nueva lista de elementos list_value_t.
*
* \param clone_item: Apuntador a la función callback que retornara la copia del valor a asignar.
* \param release_item: Apuntador a la función callback que liberara la copia del valor duplicado en el list_callback_clone_item.
* \param clone_item: Apuntador a un proceso callback que se encarga de comparar los struct list_item *.
* \return Retorna la nueva cola de datos queue_t que deberá ser destruida con list_release().
*
*/
list_t
list_allocator(list_callback_clone_item clone_item,
              list_callback_release_item release_item,
              list_callback_compare_item compare_item);

/** \brief Agrega n cantidad de elementos repetidos (value) a la lista, reemplazando los existentes.
*
* \param list: Lista en la que se agregara value n veces.
* \param n: Cantidad de valores a agregar a la lista.
* \param value: Valor a agregar n veces a la lista.
* \return Retorna el primer elemento agregado; NULL si no se a agregado ningun elemento.
*
*/
struct list_item*
list_assign(list_t list,
           size_t n,
           list_value_t value);

/** \brief Obtiene el ultimo elemento de una lista.
*
* \param list: Lista de la cual se obtendrá el ultimo elemento struct list_item *.
* \return Devuelve el ultimo struct list_item * de la lista.
*
*/
struct list_item*
list_back(list_t list);

/** \brief Obtiene el item anterior al inicado.
*
* \param item: Item pivote en la lista.
* \return Retorna el struct list_item * anterior al indicado; NULL si no hay ningun item.
*
*/
struct list_item*
list_before(struct list_item *item);

/** \brief Obtiene el primer elemento de una lista.
*
* \param list: Lista de la cual se obtendrá su primer elemento struct list_item *.
* \return Devuelve el primer struct list_item * de la lista.
*
*/
struct list_item*
list_begin(list_t list);

/** \brief Remueve/Libera TODOS los elementos de la lista.
*
* \param list: Puntero a la struct list que se limpiara.
* \return Retorna la cantidad de elementos removidos de la lista.
*
*/
size_t
list_clear(list_t list);

/** \brief Función que clona por completo una lista.
*
* \param list: Lista que será clonada.
* \return Retorna una nueva lista que deberá ser liberada con list_release().
*
*/
list_t
list_clone(list_t list);

/** \brief Copia los elementos de una lista a otra.
*
* \param list: Lista a la que pertenece el item pasado por el parámetro dst.
* \param dst: Elemento pivote en donde se se ubicaran los elementos a copiar desde src.
* \param src: Elemento pivote de una lista que se le clonaran sus elementos para agregarlos en la lista destino dst.
* \param n: Cantidad máxima de elementos que copiaran.
* \return Retorna la cantidad de elementos agregados en la lista dst.
*
*/
size_t
list_copy(list_t list,
         struct list_item *dst,
         struct list_item *src,
         size_t n);

/** \brief Verifica si una lista esta vacia.
*
* \param list: Lista que se verificara.
* \return Retorna:
*  true: si la lista esta vacia.
*  false: Si contiene por lo menos un elemento.
*
*/
bool
list_empty(list_t list);


/** \brief Elimina un struct list_item * de su lista.
*
* \param list: Lista a la que pertenece el item.
* \param item: Elemento que se eliminara/liberara de su lista.
*
*/
void
list_erase(list_t list,
          struct list_item *item);

/** \brief Libera la memoria un struct list_item * NO RELACIONADA con una lista (miembro list debe ser igual a NULL).
*
* \param item: Elemento que se eliminara/liberara de su lista.
* \param callback_release_value: Callback a la función que esta encargada de liberar la memoria del miembro value.
*
*/
void
list_release_item(struct list_item *item,
                 list_callback_release_item callback_release_value);

/** \brief Remueve la relación que tiene el elemento con su lista madre (Usar con cuidado).
*
* \param list: Lista a la que se le extraerá el elemento.
* \param item: Elemento que se extraerá de su lista.
* \return Retorno el valor pasado en el parámetro item si se extrajo correctamente, de lo contrario retorna NULL.
*
*
* \code
* void
* list_release_item(struct list_item *item,
*                   list_callback_release_item callback_release_value) {
*     if (!item)
*         return;
*
*     if (callback_release_value)
*         callback_release_value(item->value);
* #ifdef LIST_INTEGRAL_RELATIONSHIP
*     free(list_extract(NULL, item));
* #else
*     free(list_extract(NULL, item));
* #endif
* }
* \endcode
*
*/
struct list_item*
list_extract(list_t list, struct list_item *item);

/** \brief Busca un valor a partir de un pivote indicado dentro de una lista.
*
* \param list: Lista a la que pertenecen los elementos (incluye parámetro item).
* \param item: Elemento pivote desde el cual se empezara a buscar el valor indicado en value.
* si es NULL iniciara desde el inicio de la lista.
* \param value: Valor a buscar en la lista a partir de el pivote indicado.
* \return Retorna NULL si no se a encontrado dentro de la lista en caso
* contrario retorna el elemento .
*
*/
struct list_item*
list_findnext(list_t list,
             struct list_item *item,
             list_value_t value);


/** \brief Busca un valor a partir de un pivote indicado dentro de una lista.
*
* \param list: Lista a la que pertenecen los elementos.
* \param item: Elemento pivote desde el cual se empezara a buscar el valor indicado en value,
* si es NULL iniciara a buscar desde el final de la lista.
* \param value: Valor a buscar en la lista antes de el pivote indicado.
* \return Retorna NULL si no se a encontrado dentro de la lista en caso
* contrario retorna el puntero al item.
*/
struct list_item*
list_findprev(list_t list,
             struct list_item *item,
             list_value_t value);

#ifdef LIST_INTEGRAL_RELATIONSHIP
/** \brief Obtiene la lista a la cual pertenece un item.
*
* \param item: elemento a consultar.
* \return Devuelve la lista a la cual pertenece dicho item; NULL si no pertenece a ninguna lista.
*
*/
list_t
list_getlist(struct list_item *item);
#endif

/** \brief Mezcla dos listas generando una nueva lista que deberá ser liberada con list_release().
*
* \param list1: Los elementos de esta lista se agregaran al inicio.
* \param list2: Los elementos de esta lista se agregaran al seguidos de los de list1.
* \return Retorna una nueva lista que  contendrán  las copias de las dos listas espesificadas.
*
*/
list_t
list_join(list_t list1,
         list_t list2);

/** \brief Agrega un valor al final de la lista.
*
* \param list: lista a la cual se le agregara un elemento nuevo.
* \param value: Valor a agregar a la lista.
* \return Retorna el puntero al item en la lista, NULL si fallo.
*
*/
struct list_item*
list_pushback(list_t list,
             list_value_t value);

/** \brief Agrega un elemento struct list_item al final de la lista (No crea un duplicado del elemento).
*
* \param list: lista a la cual se le agregara un elemento nuevo.
* \param item: Puntero al elemento struct list_item a relacionar con la lista.
* \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro item), NULL si fallo.
*
*/
struct list_item*
list_pushback_item (list_t list,
                   struct list_item *item);

/** \brief Agrega un valor al inicio de la lista.
*
* \param list: Lista a la cual se le agregara un elemento nuevo.
* \param value: Valor a agregar a la lista.
* \return Retorna el puntero al item en la lista.
*
*/
struct list_item*
list_pushfront(list_t list,
              list_value_t value);

/** \brief Agrega un elemento struct list_item al inicio de la lista (No crea un duplicado del elemento).
*
* \param list: lista a la cual se le agregara un elemento nuevo.
* \param item: Puntero al elemento struct list_item a relacionar con la lista.
* \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro item), NULL si fallo.
*
*/
struct list_item*
list_pushfront_item (list_t list,
                    struct list_item *item);

/** \brief Agrega un valor en la lista después de un elemento indicado como pivote.
*
* \param list: lista en la que se agregara.
* \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL value se agregara al final de la lista.
* \param value: Valor a agregar a la lista después del pivote.
* \return Retorna el puntero al item en la lista, NULL si fallo.
*
*/
struct list_item*
list_pushnext(list_t list,
             struct list_item *pivot,
             list_value_t value);

/** \brief Agrega un elemento struct list_item después de un elemento indicado como pivote (No crea un duplicado del elemento).
*
* \param list: lista en la que se agregara.
* \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL itemnew se agregara al final de la lista.
* \param itemnew: Puntero al elemento struct list_item a relacionar con la lista.
* \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro itemnew), NULL si fallo.
*
*/
struct list_item*
list_pushnext_item(list_t list,
                  struct list_item *pivot,
                  struct list_item *itemnew);


/** \brief Agrega un elemento en la lista antes de un elemento indicado.
*
* \param list: lista en la que se agregara.
* \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL value se agregara al final de la lista.
* \param value: Valor a agregar a la lista antes del pivote.
* \return Retorna el puntero al item en la lista, NULL si fallo.
*
*/
struct list_item*
list_pushprev(list_t list,
             struct list_item *pivot,
             list_value_t value);

/** \brief Agrega un elemento struct list_item antes de un elemento indicado como pivote (No crea un duplicado del elemento).
*
* \param list: lista en la que se agregara.
* \param pivot: Elemento pivote que esta dentro de una lista, si el valor es NULL itemnew se agregara al final de la lista.
* \param itemnew: Puntero al elemento struct list_item a relacionar con la lista.
* \return Retorna el puntero al item en la lista (el retorno es igual a el parámetro itemnew), NULL si fallo.
*
*/
struct list_item*
list_pushprev_item(list_t list,
                  struct list_item *pivot,
                  struct list_item *itemnew);

/** \brief Destruye una lista, los elementos también son liberados.
*
* \param list: Puntero a la struct list a destruir.
*/
void
list_release(list_t list);

/** \brief Obtiene la cantidad de elementos en la lista.
*
* \param list: Lista de la cual se retornaran la cantidad de elementos almacenados en ella.
* \return Retorna la cantidad de elementos en la lista.
*
*/
size_t
list_size(list_t list);

/** \brief Intercambia los elementos de cada lista.
*
* \param list1: Lista involucrada que se cambiaran los elementos con list2.
* \param list2: Lista involucrada que se cambiaran los elementos con list1.
* \return Retorna TRUE si no hubo errores y FALSE si no se puedo intercambiar los elementos.
*
*/
void
list_swap(list_t list1,
         list_t list2);

#endif // LIST_H_INCLUDED



list.c

#include "include/List.h"

/** \brief callback predeterminado que se encarga de crear un duplicado del queue_value_t para el stack_item_t.
 *
 * \param value: queue_value_t que se asignara.
 * \return Debe retornarse el queue_value_t a asignar al stack_item_t que se esta creando.
 *
 */
list_value_t
list_callback_clone_item_default(const list_value_t value) {
   return value;
}


/** \brief callback predeterminado que se encarga de destruir la memoria asignada al stack_item_t.
 *
 * \param value: queue_value_t que se liberara.
 *
 */
void
list_callback_release_item_default(const list_value_t value) {
   /// none code
}


/** \brief callback predeterminado que se encarga comparar dos list_value_t.
 *
 * \param value1: se comparara con value2.
 * \param value2: se comparara con value1.
 * \return Retorna el resultado de la comparación.
 * LIST_CMP_LESS_THAT: Si value1 < value2.
 * LIST_CMP_EQUAL: Si value1 == value2.
 * LIST_CMP_GREATER_THAT: Si value1 > value2.
 *
 */
enum list_cmp
list_callback_compare_item_default(const list_value_t value1,
                                  const list_value_t value2) {
   if (value1 > value2) {
       return LIST_CMP_GREATER_THAT;
   } else if (value1 < value2) {
       return LIST_CMP_LESS_THAT;
   }
   return LIST_CMP_EQUAL;
}

struct list_item*
list_after(struct list_item *item) {
   return item ? item->next : NULL;
}

list_t
list_allocator(list_callback_clone_item       clone_item,
              list_callback_release_item     release_item,
              list_callback_compare_item     compare_item) {
   list_t list = malloc(sizeof (struct list));
   list->first = list->last = NULL;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   list->size = 0;
#endif //LIST_INTEGRAL_RELATIONSHIP
   list->clone_item = clone_item ? clone_item : list_callback_clone_item_default;
   list->release_item = release_item ? release_item : list_callback_release_item_default;
   list->compare_item = compare_item ? compare_item : list_callback_compare_item_default;
   return list;
}

void
list_allocator_array(list_t *array,
                    size_t n,
                    list_callback_clone_item       clone_item,
                    list_callback_release_item     release_item,
                    list_callback_compare_item     compare_item) {
   for (register size_t i = 0; i < n; ++i)
       array[i] = list_allocator(clone_item, release_item, compare_item);
}

struct list_item*
list_assign(list_t list,
           size_t n,
           list_value_t value) {
   struct list_item *ret = NULL;

   if (!list)
       return NULL;

   list_clear(list);
   ret = (n > 0) ? list_pushback(list, value) : NULL;

   for (register size_t i = 1; i < n; i++)
       list_pushback(list, value);

   return ret;
}

struct list_item*
list_back(list_t list) {
   return list ? list->last : NULL;
}

struct list_item*
list_before(struct list_item *item) {
   return item ? item->prev : NULL;
}

struct list_item*
list_begin(list_t list) {
   return list ? list->first : NULL;
}

size_t
list_clear(list_t list) {
   struct list_item *item = NULL;
   size_t     ret = 0;
   while((item = list->first) != NULL) {
       list_erase(list, item);
       ++ret;
   }
   return ret;
}

list_t
list_clone(list_t list) {
   list_t ret = NULL;
   struct list_item *item = NULL;

   if (!list)
       return NULL;

   ret = list_allocator(list->clone_item, list->release_item, list->compare_item);

   for (item = list_begin(list); item != NULL; item = list_after(item))
       list_pushback(ret, item->value);

   return ret;
}

size_t
list_copy(list_t list,
         struct list_item *dst,
         struct list_item *src,
         size_t n) {
   size_t ret = 0;

   if (!(dst && src)) return 0;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   if (!(dst->list && dst->list == list)) return 0;
#endif //LIST_INTEGRAL_RELATIONSHIP

   while (n > 0 && src != NULL) {
       list_pushback(list, src->value);
       src = src->next;
       --n; ++ret;
   }

   return ret;
}

bool
list_empty(list_t list) {
   return  list && list->first && list->last ? true : false;
}

void
list_erase(list_t list,
          struct list_item *item) {
   if (!(item && list)) return;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (item->list != list) return;
#endif //LIST_INTEGRAL_RELATIONSHIP
   if (list && list->release_item)
       list->release_item(item->value);

   free(list_extract(list, item));
}

void
list_release_item(struct list_item *item,
                 list_callback_release_item callback_release_value) {
   if (!item)
       return;

   if (callback_release_value)
       callback_release_value(item->value);
#ifdef LIST_INTEGRAL_RELATIONSHIP
   free(list_extract(NULL, item));
#else
   free(list_extract(NULL, item));
#endif // LIST_INTEGRAL_RELATIONSHIP
}

struct list_item*
list_extract(list_t list,
            struct list_item *item) {
   if (!item) return NULL;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (item->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   if (list) {
       if (list->first == item) list->first = item->next;
       if (list->last == item) list->last = item->prev;

   } else if (item->prev || item->next) {
       return NULL;
   }
   if (item->prev) item->prev->next = item->next;
   if (item->next) item->next->prev = item->prev;
   item->prev = NULL;
   item->next = NULL;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   --(list->size);
   item->list = NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP
   return item;
}

struct list_item*
list_findnext(list_t list,
             struct list_item *item,
             list_value_t value) {

   if (!list) return NULL;
   else if (!list->compare_item) return NULL;
   if (!item) item = list->first;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (item->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   struct list_item   *now = item;

   do {
       if ((list->compare_item)(now->value, value) & LIST_CMP_EQUAL)
           return now;
       now = now->next;
   } while (now);

   return NULL;
}

struct list_item*
list_findprev(list_t list,
             struct list_item *item,
             list_value_t value) {
   if (!list) return NULL;
   else if (!list->compare_item) return NULL;
   if (!item) item = list->last;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (item->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   struct list_item   *now = item;

   do {
       if ((list->compare_item)(now->value, value) & LIST_CMP_EQUAL)
           return now;
       now = now->prev;
   } while (now);

   return NULL;
}

#ifdef LIST_INTEGRAL_RELATIONSHIP
list_t
list_getlist(struct list_item *item) {
   if (!item) return NULL;
   return item->list;
}
#endif // LIST_INTEGRAL_RELATIONSHIP

list_t
list_join(list_t list1,
         list_t list2) {
   list_t              list = list_clone(list1);
   struct list_item    *item = NULL;

   for (item = list_begin(list2); item != NULL; item = list_after(item))
       list_pushback(list, item->value);
   return list;
}

struct list_item*
list_pushback(list_t list,
             list_value_t value) {
   struct list_item   *itemnew = NULL;

   if (list && !list->clone_item)
       return NULL;

   itemnew = malloc(LIST_SIZE_ITEM);
#ifdef LIST_INTEGRAL_RELATIONSHIP
   itemnew->list = NULL;
#endif

   if (list_pushback_item(list, itemnew) != itemnew) {
       free(itemnew);
       return NULL;
   }

   itemnew->value = (list->clone_item)(value);

   return list->last;
}

struct list_item*
list_pushback_item (list_t list,
                   struct list_item *item) {
#ifdef LIST_INTEGRAL_RELATIONSHIP
   if (!(list && item && !item->list))
       return NULL;
#else
   if (!(list && item))
       return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   if (!(list->first && list->last)) {
       list->first = item;
       item->prev = NULL;
   } else {
       list->last->next = item;
       item->prev = list->last;
   }

   item->next = NULL;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   ++(list->size);
   item->list = list;
#endif // LIST_INTEGRAL_RELATIONSHIP
   list->last = item;

   return item;
}

struct list_item*
list_pushfront(list_t list,
              list_value_t value) {
   struct list_item   *itemnew = NULL;

   if (list || !list->clone_item)
       return NULL;

   itemnew = malloc(LIST_SIZE_ITEM);
#ifdef LIST_INTEGRAL_RELATIONSHIP
   itemnew->list = NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   if (list_pushfront_item(list, itemnew) != itemnew) {
       free(itemnew);
       return NULL;
   }
   itemnew->value = (list->clone_item)(value);

   return list->first;
}

struct list_item*
list_pushfront_item(list_t list,
                   struct list_item *item) {
#ifdef LIST_INTEGRAL_RELATIONSHIP
   if (!(list && item && !item->list))
       return NULL;
#else
   if (!(list && item))
       return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   if (!(list->first && list->last)) {
       list->last = item;
       item->next = NULL;
   } else {
       list->first->prev = item;
       item->next = list->first;
   }

   item->prev = NULL;

#ifdef LIST_INTEGRAL_RELATIONSHIP
   ++(list->size);
   item->list = list;
#endif // LIST_INTEGRAL_RELATIONSHIP

   list->first = item;

   return item;
}

struct list_item*
list_pushnext(list_t list,
             struct list_item *pivot,
             list_value_t value) {
   if (!list) return NULL;
   if (!pivot) pivot = list->last;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (pivot->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   struct list_item *itemnew = malloc(LIST_SIZE_ITEM);

   if (list_pushnext_item(list, pivot, itemnew) != itemnew) {
       free(itemnew);
       return NULL;
   }

   itemnew->value = (list->clone_item)(value);

   return itemnew;
}

struct list_item*
list_pushnext_item(list_t list,
                  struct list_item *pivot,
                  struct list_item *itemnew) {

   if (!(list && itemnew)) return NULL;
   if (!pivot) pivot = list->last;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (pivot->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   if (pivot) {
       if (!pivot->next)
           return list_pushback_item(list, itemnew);
       pivot->next->prev = itemnew;
       itemnew->next = pivot->next;
       pivot->next = itemnew;
       itemnew->prev = pivot;
#ifdef LIST_INTEGRAL_RELATIONSHIP
       ++(itemnew->list->size);
       itemnew->list = pivot->list;
#endif // LIST_INTEGRAL_RELATIONSHIP
       return itemnew;
   } else {
       return list_pushback_item(list, itemnew);
   }

   return NULL;
}

struct list_item*
list_pushprev(list_t list,
             struct list_item *pivot,
             list_value_t value) {

   if (!list) return NULL;
   if (!pivot) pivot = list->first;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (pivot->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   struct list_item *itemnew = malloc(LIST_SIZE_ITEM);

   if (list_pushprev_item(list, pivot, itemnew) != itemnew) {
       free(itemnew);
       return NULL;
   }

   itemnew->value = (list->clone_item)(value);

   return itemnew;
}

struct list_item*
list_pushprev_item(list_t list,
                  struct list_item *pivot,
                  struct list_item *itemnew) {

   if (!(list && itemnew)) return NULL;
   if (!pivot) pivot = list->first;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   else if (pivot->list != list) return NULL;
#endif // LIST_INTEGRAL_RELATIONSHIP

   if (pivot) {
       if (!pivot->prev)
           return list_pushfront_item(list,itemnew);
       pivot->prev->next = itemnew;
       itemnew->prev = pivot->prev;
       pivot->prev = itemnew;
       itemnew->next = pivot;
#ifdef LIST_INTEGRAL_RELATIONSHIP
       itemnew->list = pivot->list;
       ++(itemnew->list->size);
#endif // LIST_INTEGRAL_RELATIONSHIP
       return itemnew;
   } else {
       return list_pushfront_item(list,itemnew);
   }

   return NULL;
}

void
list_release(list_t list) {
   list_clear(list);
   free(list);
}

void
list_release_array(list_t *array,
                  size_t n) {
   for (register size_t i = 0; i < n; ++i)
       list_release(array[i]);
}

size_t
list_size(list_t list) {
#ifdef LIST_INTEGRAL_RELATIONSHIP
   return list ? list->size : 0;
#else
   size_t ret = 0;
   struct list_item *item = list ? list->first : NULL;
   while (item) {
       ++ret;
       item = item->next;
   }
   return ret;
#endif // LIST_INTEGRAL_RELATIONSHIP
}

void
list_swap(list_t list1,
         list_t list2) {
   if (!(list1 && list2)) return;
   struct list tmp = *list2;
   *list2 = *list1;
   *list1 = tmp;
#ifdef LIST_INTEGRAL_RELATIONSHIP
   for (struct list_item *item = list_begin(list1); item != NULL; item = list_after(item))
       item->list = list1;
   for (struct list_item *item = list_begin(list2); item != NULL; item = list_after(item))
       item->list = list2;
#endif // LIST_INTEGRAL_RELATIONSHIP
}


Dulces Lunas!¡.
The Dark Shadow is my passion.

BlackZeroX

#1
Dos simples códigos de ejemplo:

Use algunos Cast para que se entienda...

Solo numeros o punteros o cualquier cosa no mayor a un sizeof(list_value_t).

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <inttypes.h>
//#include "include/CSAVL.h"
//#include "include/CSMap.h"
#include "include/CSList.h"
//#include "include/CSQueue.h"
//#include "include/CScript.h"
//#include "include/CSUtiles.h"

uint32_t min(uint32_t a, uint32_t b);
void    swap(int32_t *a, int32_t *b);
int32_t randomnumber(int32_t lower, int32_t upper);
void    test();

int main() {
   list_t list1 = list_allocator(NULL, NULL, NULL);
   struct list_item *item = NULL;

   puts("Prueba de list_t");

   puts("Ingresando datos.");
   for (uint_fast32_t i = 0; i < VALUES_TO_ADD; ++i) {
       list_pushback(list1, randomnumber(0, 100));
   }
   puts("fin de insercion de los datos.\n");

   puts("Liberando memoria de list_t"); list_clear(list1);
   printf("\n\nOK\n");
   getchar();

   return EXIT_SUCCESS;
}

uint32_t min(uint32_t a, uint32_t b) {
   return (a<b) ? a:b;
}

void swap(int32_t *a, int32_t *b) {
   *a ^= *b;
   *b ^= *a;
   *a ^= *b;
}

int32_t randomnumber(int32_t lower, int32_t upper) {
   if (min(lower, upper) != lower) {
       swap(&lower, &upper);
   }
   return lower + rand() % ((upper + 1) - lower);
}


Con estructuras:


struct persona_datos {
   char *nombre;
   char apellido[256];
   unsigned edad;
};
long    min(uint32_t a, uint32_t b);
void    swap(int32_t *a, int32_t *b);
int32_t randomnumber(int32_t lower, int32_t upper);
void    test();


list_value_t
callback_clone_item(const list_value_t value) {
   if (!value) return NULL; /**< No hay nada que clonar */
   struct persona_datos *__ptr = (struct persona_datos *)value; /**< Original */
   struct persona_datos *__new = (struct persona_datos *)malloc(sizeof (struct persona_datos));
   size_t __ln = 0;

   if (__ptr->nombre) { // nombre es un puntero a un array char por ello reservamos memoria.
       if ((__ln = strlen(__ptr->nombre)) > 0) {
           __new->nombre = (char*)malloc((__ln + 1));// * sizeof(char)); // Omitimos.
           strcpy(__new->nombre, __ptr->nombre);
       }
   }
   strcpy(__new->apellido, __ptr->apellido); // apellido e suna rray no un puntero...
   __new->edad = __ptr->edad;

   return (list_value_t)__new; /**< retornamos __new. */
}

void
callback_release_item(const list_value_t value) {
   if (!value) return; /**< No hay nada que liberar */
   struct persona_datos *__ptr = (struct persona_datos *)value; /**< Original esta se creo en el callback callback_clone_item() */
   free(__ptr->nombre);
   free(__ptr);
}

enum list_cmp
callback_compare_item(const list_value_t value1,
                     const list_value_t value2) {
   struct persona_datos *__ptr1 = (struct persona_datos *)value1;
   struct persona_datos *__ptr2 = (struct persona_datos *)value2;
   /**< Comparamos las edades */
   if (__ptr1->edad > __ptr2->edad) {
       return LIST_CMP_GREATER_THAT;
   } else if (__ptr1->edad < __ptr2->edad) {
       return LIST_CMP_LESS_THAT;
   }
   return LIST_CMP_EQUAL;
}

int main() {
   list_t list1 = list_allocator(callback_clone_item,
                                 callback_release_item,
                                 callback_compare_item);
   struct persona_datos dato = {};
   char buff[256] = {}; /**< Buffer usado en miembro nombre. */

   puts("Prueba de list_t");

   puts("Ingresando datos.");
   dato.nombre = buff;
   for (uint_fast32_t i = 0; i < VALUES_TO_ADD; ++i) {
       dato.edad = randomnumber(0, 100);
       sprintf(dato.nombre, "Nombre %"PRIdFAST32, i); /**< dato.nombre apunta a un buffer de 256 caracteres */
       sprintf(dato.apellido, "Apellido %"PRIdFAST32, i);
       list_pushback(list1, (list_value_t)&dato);
   }
   puts("fin de insercion de los datos.\n");

   puts("Liberando memoria de list_t"); list_clear(list1);
   printf("\n\nOK\n");
   getchar();

   return EXIT_SUCCESS;
}


Dulces Lunas!¡.
The Dark Shadow is my passion.