#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