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!¡.
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!¡.