*=====================================================================================*/
LL_Error LL_SubscribeOnItemRemovingNotification(LL_LinkedList *list, LL_ItemRemovingNotification callback)
{
if (NULL == list || NULL == callback)
{
return LL_ERR_BADPARAM;
}
list->ItemRemovingNotification = callback;
return LL_ERR_OK;
}
/*=======================================================================================
* Подписаться на нотификацию о сортировке. Данные пользователя для модуля непрозрачны
* поэтому сравнивать он их не может. Сравнивать пары элементов пользователь должен
* самостоятельно и возвращать результаты сравнения.
*=====================================================================================*/
LL_Error LL_SubscribeOnSortNotification(LL_LinkedList *list, LL_CompareItems_cb callback)
{
if (NULL == list || NULL == callback)
{
return LL_ERR_BADPARAM;
}
list->ItemSortNotification = callback;
return LL_ERR_OK;
}
/*========================================================================================
* Сортировать лист. Для использования этой функциональности внешний модуль должен
* подписать на нотификацию о сортировке. См. LL_SubscribeOnSortNotification()
*======================================================================================*/
LL_Error LL_SortList(LL_LinkedList *list, LL_SortOreder order)
{
LL_Item *item = NULL;
boolean continueSort = TRUE; //флаг необходимости продолжения сортировки
void *t = NULL; //временная переменная при смене элементов местами
int cmp = 0;
cmp = order == LL_SORT_DECREASE ? -1 : 1; //определение порядка сортировки
//проверка входных данных
if (NULL == list || NULL == list->ItemSortNotification)
{
return LL_ERR_BADPARAM;
}
// сортировка методом пузырька
while (continueSort)
{
continueSort = FALSE; //сбросить флаг продолжения сортировки
item = list->first;
while (NULL != item->next)
{
//сравнение двух элементов – вызов пользовательского «колбэка»
int res = list->ItemSortNotification(item->data, item->next->data);
if ((cmp < 0 && res < 0) || (cmp > 0 && res >0))
{
t = item->data;
item->data = item->next->data;
item->next->data = t;
continueSort = TRUE; //установка флага продолжения сортировки
}
item = item->next;
}
}
return LL_ERR_OK;
}
/*========================================================================================
* Очистка памяти – удаление всех элементов списка и LL_LinkedList.
* Пользователь должен быть подписан на нотификацию об удалении элемента (см.
* LL_SubscribeOnItemRemovingNotification), иначе функция вернет предупреждение о возможной
* утечке памяти - LL_ERR_MEMORYLEAK. Если пользователь уверен, что его данные не содержат
* в своей структуре указателей, он может выставить флажок disableWarning в TRUE
* (это отключит предупреждение о возможной утечке памяти LL_ERR_MEMORYLEAK).
*======================================================================================*/
LL_Error LL_RemoveAll(LL_LinkedList **list, boolean disableWarning)
{
LL_Error err = LL_ERR_OK;
LL_Item *tofree = NULL;
// проверка корректности входных данных
if (NULL == list || NULL == (*list) || NULL == (*list)->first || NULL == (*list)->last || NULL == (*list)->current)
{
return LL_ERR_BADPARAM;
}
//установка предупреждения о возможной утечке памяти (функция продолжает выполняться)
if (!disableWarning && NULL == (*list)->ItemRemovingNotification)
{
err = LL_ERR_MEMORYLEAK;
}
// удаление элементов из памяти
LL_MoveToItem(*list, LL_MOVETO_FIRST);
do
{
tofree = (*list)->current;
(*list)->current = tofree->next;
if (NULL != (*list)->ItemRemovingNotification)
{
//запрос пользовательского «колбэка» на удаление указателей в его данных
(*list)->ItemRemovingNotification(tofree->data);
}
//пользователь должен удалить только указатели внутри своей структуры
//удаление же самой структуры данных пользователя происходит здесь
if (tofree->data) free(tofree->data); //удаление пользовательских данных
free(tofree); //удаление элемента
} while (NULL != (*list)->current);
// удаление LL_LinkedList (связного списка)
free((*list));
(*list) = NULL; //пользователю возвращают очищенные данные
return err;
}
«LListcmn.h» – общий заголовочный файл для модуля двусвязного списка и внешних модулей.
#ifndef __LLISTCMN_H__
#define __LLISTCMN_H__
#include "macro.h"
typedef enum LL_Error
{
LL_ERR_OK,
LL_ERR_BADPARAM = -1, //некорректные входные параметры
LL_ERR_NOMEMORY = -2, //отказ в выделении памяти
LL_ERR_ENDLIST = -3, //уведомление: достигнут конец списка (начало/конец)
LL_ERR_MEMORYLEAK = -4, //предупреждение: возможна утечка памяти
LL_ERR_MEMORYCORRUPTION = -5 //предупреждение: возможно повреждение памяти (утечка памяти уже случилась)
} LL_Error;
typedef enum LL_MoveTo //директивы передвижения по списку
{
LL_MOVETO_FIRST,
LL_MOVETO_PREV,
LL_MOVETO_NEXT,
LL_MOVETO_LAST
} LL_MoveTo;
typedef enum LL_SortOreder //порядок сортировки
{
LL_SORT_NOTSORTED,
LL_SORT_INCREASE,
LL_SORT_DECREASE
} LL_SortOreder;
/*=====================================================================================
* «Колбэк» для нотификации об удалении элемента. См. LL_SubscribeOnItemRemovingNotification
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.