#ifndef UCS_HLIST_H_
#define UCS_HLIST_H_
#include "list.h"
#include <stddef.h>
BEGIN_C_DECLS
typedef struct ucs_hlist_link {
ucs_list_link_t list;
} ucs_hlist_link_t;
typedef struct ucs_hlist_head {
ucs_hlist_link_t *ptr;
} ucs_hlist_head_t;
static UCS_F_ALWAYS_INLINE void
ucs_hlist_head_init(ucs_hlist_head_t *head)
{
head->ptr = NULL;
}
static UCS_F_ALWAYS_INLINE int
ucs_hlist_is_empty(const ucs_hlist_head_t *head)
{
return head->ptr == NULL;
}
static UCS_F_ALWAYS_INLINE void
ucs_hlist_add_common(ucs_hlist_head_t *head, ucs_hlist_link_t *elem,
int set_head_to_elem)
{
if (head->ptr == NULL) {
head->ptr = elem;
ucs_list_head_init(&elem->list);
} else {
ucs_list_insert_before(&head->ptr->list, &elem->list);
if (set_head_to_elem) {
head->ptr = elem;
}
}
}
static UCS_F_ALWAYS_INLINE void
ucs_hlist_add_head(ucs_hlist_head_t *head, ucs_hlist_link_t *elem)
{
ucs_hlist_add_common(head, elem, 1);
}
static UCS_F_ALWAYS_INLINE void
ucs_hlist_add_tail(ucs_hlist_head_t *head, ucs_hlist_link_t *elem)
{
ucs_hlist_add_common(head, elem, 0);
}
static UCS_F_ALWAYS_INLINE void
ucs_hlist_del_common(ucs_hlist_head_t *head, ucs_hlist_link_t *elem,
int is_head)
{
if (ucs_list_is_empty(&elem->list)) {
head->ptr = NULL;
} else {
if (is_head) {
head->ptr = ucs_list_next(&elem->list, ucs_hlist_link_t, list);
}
ucs_list_del(&elem->list);
}
}
static UCS_F_ALWAYS_INLINE void
ucs_hlist_del(ucs_hlist_head_t *head, ucs_hlist_link_t *elem)
{
ucs_hlist_del_common(head, elem, elem == head->ptr);
}
static UCS_F_ALWAYS_INLINE ucs_hlist_link_t*
ucs_hlist_extract_head(ucs_hlist_head_t *head)
{
ucs_hlist_link_t *elem;
if (head->ptr == NULL) {
return NULL;
}
elem = head->ptr;
ucs_hlist_del_common(head, elem, 1);
return elem;
}
#define ucs_hlist_head_elem(_head, _type, _member) \
ucs_container_of((_head)->ptr, _type, _member)
#define ucs_hlist_next_elem(_elem, _member) \
ucs_container_of(ucs_list_next(&(_elem)->_member.list, ucs_hlist_link_t, \
list), \
ucs_typeof(*(_elem)), _member)
#define ucs_hlist_for_each(_elem, _head, _member) \
for (_elem = NULL; \
(_elem == NULL) ? \
\
(!ucs_hlist_is_empty(_head) && \
((_elem = ucs_hlist_head_elem(_head, ucs_typeof(*(_elem)), _member)) \
!= NULL)) : \
\
((_elem = ucs_hlist_next_elem(_elem, _member)) != \
ucs_hlist_head_elem(_head, ucs_typeof(*(_elem)), _member)); \
)
#define ucs_hlist_extract_head_elem(_head, _type, _member) \
ucs_container_of(ucs_hlist_extract_head(_head), _type, _member)
#define ucs_hlist_for_each_extract(_elem, _head, _member) \
for (_elem = ucs_hlist_extract_head_elem(_head, ucs_typeof(*(_elem)), _member); \
_elem != UCS_PTR_BYTE_OFFSET(NULL, -ucs_offsetof(ucs_typeof(*(_elem)), _member)); \
_elem = ucs_hlist_extract_head_elem(_head, ucs_typeof(*(_elem)), _member))
#define ucs_hlist_for_each_extract_if(_elem, _head, _member, _cond) \
for (_elem = ucs_hlist_head_elem(_head, ucs_typeof(*(_elem)), _member); \
(_elem != UCS_PTR_BYTE_OFFSET(NULL, -ucs_offsetof(ucs_typeof(*(_elem)), \
_member))) && \
(_cond) && ucs_hlist_extract_head(_head); \
_elem = ucs_hlist_head_elem(_head, ucs_typeof(*(_elem)), _member))
END_C_DECLS
#endif