Разработка программы для создания и работы с двусвязным списком, состоящим из структур. (Структура содержит фамилию и год рождения), страница 6

        err = LL_ERR_NOMEMORY;

    }

    return err;

}

/*=======================================================================================

* Добавляет новый элемент в конец списка.

* data – данные пользователя, которые будут храниться в новом элементе

*=====================================================================================*/

LL_Error LL_PushLast(LL_LinkedList *list, void *data)

{

    LL_Item *newItem = NULL;

    if (NULL == list || NULL == data)

    {

        return LL_ERR_BADPARAM;

    }

    // выделение памяти для

    newItem = (LL_Item*)malloc(sizeof(LL_Item));

    if (NULL == newItem)

    {

        return LL_ERR_NOMEMORY;

    }

    // инициализация полей данных нового элемента

    newItem->prev = list->last;

    newItem->next = NULL;

    newItem->data = data;

    // если новый элемент не первый в списке (последний элемент уже существует)

    if (NULL != list->last)

    {

        list->last->next = newItem;

    }

    // добавить новый элемент в конец списка

    list->last = newItem;

    // если новый элемент первый в списке (единственный)

    if (NULL == list->first)

    {

        list->first = newItem;

        list->current = newItem;

    }

    return LL_ERR_OK;

}

/*========================================================================================

* Добавить новый элемент в соответствии с сортировкой списка. Для использования этой

* функциональности внешний модуль должен подписать на нотификацию о сортировке.

* См. LL_SubscribeOnSortNotification()

*======================================================================================*/

LL_Error LL_PushInSortOrder(LL_LinkedList *list, LL_SortOreder order, void *data)

{

    LL_Item *item = NULL;

    LL_Item *newItem = NULL;

    int cmp = order == LL_SORT_DECREASE ? 1 : -1; //определение порядка сортировки

    if (NULL == list || NULL == list->ItemSortNotification)

    {

        return LL_ERR_BADPARAM;

    }

    // выделение памяти для нового элемента

    newItem = (LL_Item*)malloc(sizeof(LL_Item));

    if (NULL == newItem)

    {

        return LL_ERR_NOMEMORY;

    }   

    // поиск места для нового места в соответствии с заданным порядком сортировки

    item = list->first;

    while (NULL != item)

    {

        // вызов пользовательского «колбэка» для получения результата сравнения данных

        int res = list->ItemSortNotification(data, item->data);

        if ((cmp < 0 && res < 0) || (cmp > 0 && res >0))

        {

            break;

        }

        item = item->next;

    }

    // добавление нового элемента в список

    if (NULL != item)  // добавление в начало или середину списка

    {

        newItem->prev = item->prev;

        newItem->next = item;

        newItem->data = data;

        item->prev = newItem;

        if (item == list->first)  //если элемент добавляется в начало

        {

            list->first = newItem;

        }

        else if (NULL != newItem->prev)  //если в середину

        {

            newItem->prev->next = newItem;

        }

    }

    else if (NULL != list->last)    //добавление в конец списка

    {

        newItem->prev = list->last;

        newItem->next = NULL;

        newItem->data = data;

        list->last = newItem;

        newItem->prev->next = newItem;

    }

    else              //если это первый (единственный) элемент в списке

    {

        newItem->prev = NULL;

        newItem->next = NULL;

        newItem->data = data;

        list->first = newItem;

        list->current = newItem;

    }

    return LL_ERR_OK;

}

/*=======================================================================================

* Движение по списку. Элемент, на котором остановилось движение запоминается в

* LL_LinkedList::current

*======================================================================================*/

LL_Error LL_MoveToItem(LL_LinkedList *list, LL_MoveTo dir)

{

    LL_Error err = LL_ERR_ENDLIST;

    if (NULL == list || NULL == list->first || NULL == list->last || NULL == list->current)

    {

        return LL_ERR_BADPARAM;

    }

    switch (dir)

    {

        case LL_MOVETO_FIRST:         //перейти к первому элементу

            list->current = list->first;

            break;

        case LL_MOVETO_PREV:   //к предыдущему (если он есть)

            if (NULL != list->current->prev)

            {

                list->current = list->current->prev;

                err = LL_ERR_OK;

            }

            break;

        case LL_MOVETO_NEXT:   //к следующему (если он есть)

            if (NULL != list->current->next)

            {

                list->current = list->current->next;

                err = LL_ERR_OK;

            }

            break;

        case LL_MOVETO_LAST:   //к последнему

            list->current = list->last;

            break;

    }

    return err;

}

/*========================================================================================

* Получить данные из элемента на котором остановилось движение (LL_LinkedList::current).

* См. LL_MoveToItem()

*======================================================================================*/

void* LL_GetData(LL_LinkedList *list)

{

    if (NULL == list || NULL == list->current)

    {

        return NULL;

    }

    return list->current->data;

}

/*======================================================================================

* Подписаться на нотификацию об удалении элемента. Это необходимо если данные

* пользователя содержат в своей структуре указатели. Для данного модуля, данные

* пользователя непрозрачны, поэтому пользователем обязан сам удалять указатели в

* своих данных. Нотификация приходит на удалении каждого отдельного элемента.