blob: 7b22f17d148c8ea183028ac62f35eda82ea6bdc1 (
plain) (
tree)
|
|
/* vim:ts=8:sts=8:sw=4:noai:noexpandtab
*
* portable doubly-linked list.
*
* Copyright (c) 2010 Miru Limited.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <impl/framework.h>
//#define LIST_DEBUG
pgm_list_t*
pgm_list_append (
pgm_list_t* restrict list,
void* restrict data
)
{
pgm_list_t* new_list;
pgm_list_t* last;
new_list = pgm_new (pgm_list_t, 1);
new_list->data = data;
new_list->next = NULL;
if (list)
{
last = pgm_list_last (list);
last->next = new_list;
new_list->prev = last;
return list;
}
else
{
new_list->prev = NULL;
return new_list;
}
}
pgm_list_t*
pgm_list_prepend_link (
pgm_list_t* restrict list,
pgm_list_t* restrict link_
)
{
pgm_list_t* new_list = link_;
pgm_return_val_if_fail (NULL != link_, list);
new_list->next = list;
new_list->prev = NULL;
if (list)
list->prev = new_list;
return new_list;
}
static inline
pgm_list_t*
_pgm_list_remove_link (
pgm_list_t* list, /* list and link_ may be the same */
pgm_list_t* link_
)
{
if (PGM_LIKELY (NULL != link_))
{
if (link_->prev)
link_->prev->next = link_->next;
if (link_->next)
link_->next->prev = link_->prev;
if (link_ == list)
list = list->next;
link_->next = link_->prev = NULL;
}
return list;
}
pgm_list_t*
pgm_list_remove_link (
pgm_list_t* list, /* list and link_ may be the same */
pgm_list_t* link_
)
{
return _pgm_list_remove_link (list, link_);
}
pgm_list_t*
pgm_list_delete_link (
pgm_list_t* list, /* list and link_ may be the same */
pgm_list_t* link_
)
{
pgm_list_t* new_list = _pgm_list_remove_link (list, link_);
pgm_free (link_);
return new_list;
}
/* Has pure attribute as NULL is a valid list
*/
pgm_list_t*
pgm_list_last (
pgm_list_t* list
)
{
if (PGM_LIKELY (NULL != list)) {
while (list->next)
list = list->next;
}
return list;
}
unsigned
pgm_list_length (
pgm_list_t* list
)
{
unsigned length = 0;
while (list)
{
length++;
list = list->next;
}
return length;
}
/* eof */
|