liba 0.1.15

An algorithm library based on C/C++
Documentation
/*!
 @file que.h
 @brief basic queue library
*/

#ifndef LIBA_QUE_H
#define LIBA_QUE_H

#include "list.h"

/*!
 @ingroup liba
 @addtogroup a_que basic queue library
 @{
*/

/*!
 @brief instance structure for basic queue
*/
typedef struct a_que
{
    a_list head_; /*!< element head */
    a_list **ptr_; /*!< mempool block */
    a_size siz_; /*!< element sizeof */
    a_size num_; /*!< element number */
    a_size cur_; /*!< mempool cursor */
    a_size mem_; /*!< mempool memory */
} a_que;

/*!
 @brief access size of a element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
*/
A_INTERN a_size a_que_siz(a_que const *ctx) { return ctx->siz_; }

/*!
 @brief access number of element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
*/
A_INTERN a_size a_que_num(a_que const *ctx) { return ctx->num_; }

/*!
 @brief access foremost element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @note should check if queue is empty
 @return element pointer
*/
A_INTERN void *a_que_fore_(a_que const *ctx)
{
    return a_cast_s(void *, ctx->head_.next + 1);
}
#define A_QUE_FORE_(T, ctx) a_cast_s(T *, a_que_fore_(ctx))

/*!
 @brief access backmost element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @note should check if queue is empty
 @return element pointer
*/
A_INTERN void *a_que_back_(a_que const *ctx)
{
    return a_cast_s(void *, ctx->head_.prev + 1);
}
#define A_QUE_BACK_(T, ctx) a_cast_s(T *, a_que_back_(ctx))

/*!
 @brief access foremost element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @return element pointer
  @retval 0 empty queue
*/
A_INTERN void *a_que_fore(a_que const *ctx)
{
    return ctx->head_.next != &ctx->head_ ? a_que_fore_(ctx) : A_NULL;
}
#define A_QUE_FORE(T, ctx) a_cast_s(T *, a_que_fore(ctx))

/*!
 @brief access backmost element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @return element pointer
  @retval 0 empty queue
*/
A_INTERN void *a_que_back(a_que const *ctx)
{
    return ctx->head_.prev != &ctx->head_ ? a_que_back_(ctx) : A_NULL;
}
#define A_QUE_BACK(T, ctx) a_cast_s(T *, a_que_back(ctx))

/*!
 @brief swap elements lhs and rhs for a pointer to queue structure
 @param[in] lhs element pointer on the left
 @param[in] rhs element pointer on the right
*/
A_INTERN void a_que_swap_(void *lhs, void *rhs)
{
    a_list_swap_node(a_cast_s(a_list *, lhs) - 1, a_cast_s(a_list *, rhs) - 1);
}

#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */

/*!
 @brief allocate a pointer to queue structure from memory
 @param[in] size size of element
*/
A_EXTERN a_que *a_que_new(a_size size);

/*!
 @brief deallocate a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] dtor element destructor
*/
A_EXTERN void a_que_die(a_que *ctx, void (*dtor)(void *));

/*!
 @brief constructor for queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] size size of element
*/
A_EXTERN void a_que_ctor(a_que *ctx, a_size size);

/*!
 @brief destructor for queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] dtor element destructor
*/
A_EXTERN void a_que_dtor(a_que *ctx, void (*dtor)(void *));

/*!
 @brief initialize a pointer to queue structure by moving
 @param[in] ctx points to an instance of queue structure
 @param[in] obj input source pointing to an instance
*/
A_EXTERN void a_que_move(a_que *ctx, a_que *obj);

/*!
 @brief access specified element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] idx index of element, 0 ~ n-1, -n ~ -1
 @return element pointer
  @retval 0 out of bounds
*/
A_EXTERN void *a_que_at(a_que const *ctx, a_diff idx);
#define A_QUE_AT(T, ctx, idx) a_cast_s(T *, a_que_at(ctx, idx))

/*!
 @brief drop all the elements for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] dtor current element destructor
 @return the execution state of the function
  @retval 0 success
  @retval 1 failure
*/
A_EXTERN int a_que_drop(a_que *ctx, void (*dtor)(void *));

/*!
 @brief edit size of a element for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] size the size of the new element
 @param[in] dtor previous element destructor
 @return the execution state of the function
  @retval 0 success
  @retval 1 failure
*/
A_EXTERN int a_que_edit(a_que *ctx, a_size size, void (*dtor)(void *));

/*!
 @brief swap elements lhs and rhs for a pointer to queue structure
 @param[in] ctx points to an instance of queue structure
 @param[in] lhs element index on the left
 @param[in] rhs element index on the right
 @return the execution state of the function
  @retval 0 success
  @retval 1 failure
*/
A_EXTERN int a_que_swap(a_que const *ctx, a_size lhs, a_size rhs);

/*!
 @brief insert sort foremost element for a pointer to queue structure
 @code{.c}
 T *obj = A_QUE_PUSH_FORE(T, ctx);
 if (obj)
 {
     CTOR(obj);
     INIT(obj);
     a_que_sort_fore(ctx, cmp);
 }
 @endcode
 @param[in] ctx points to an instance of queue structure
 @param[in] cmp a function that compares two elements
  @arg cmp(lhs,rhs)==0 *lhs is equivalent to *rhs
  @arg cmp(lhs,rhs)<0 *lhs goes before *rhs
  @arg cmp(lhs,rhs)>0 *lhs goes after *rhs
*/
A_EXTERN void a_que_sort_fore(a_que const *ctx, int (*cmp)(void const *, void const *));

/*!
 @brief insert sort backmost element for a pointer to queue structure
 @code{.c}
 T *obj = A_QUE_PUSH_BACK(T, ctx);
 if (obj)
 {
     CTOR(obj);
     INIT(obj);
     a_que_sort_back(ctx, cmp);
 }
 @endcode
 @param[in] ctx points to an instance of queue structure
 @param[in] cmp a function that compares two elements
  @arg cmp(lhs,rhs)==0 *lhs is equivalent to *rhs
  @arg cmp(lhs,rhs)<0 *lhs goes before *rhs
  @arg cmp(lhs,rhs)>0 *lhs goes after *rhs
*/
A_EXTERN void a_que_sort_back(a_que const *ctx, int (*cmp)(void const *, void const *));

/*!
 @brief push an element into the queue and sort it
 @param[in] ctx points to an instance of queue structure
 @param[in] key the key on the right for insertion sort
 @param[in] cmp a function that compares two elements
  @arg cmp(lhs,rhs)==0 *lhs is equivalent to *rhs
  @arg cmp(lhs,rhs)<0 *lhs goes before *rhs
  @arg cmp(lhs,rhs)>0 *lhs goes after *rhs
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_push_sort(a_que *ctx, void const *key, int (*cmp)(void const *, void const *));
#define A_QUE_PUSH_SORT(T, ctx, key, cmp) a_cast_s(T *, a_que_push_sort(ctx, key, cmp))

/*!
 @brief push an element into the queue forward
 @param[in] ctx points to an instance of queue structure
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_push_fore(a_que *ctx);
#define A_QUE_PUSH_FORE(T, ctx) a_cast_s(T *, a_que_push_fore(ctx))

/*!
 @brief push an element into the queue backward
 @param[in] ctx points to an instance of queue structure
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_push_back(a_que *ctx);
#define A_QUE_PUSH_BACK(T, ctx) a_cast_s(T *, a_que_push_back(ctx))

/*!
 @brief pull an element from the queue forward
 @param[in] ctx points to an instance of queue structure
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_pull_fore(a_que *ctx);
#define A_QUE_PULL_FORE(T, ctx) a_cast_s(T *, a_que_pull_fore(ctx))

/*!
 @brief pull an element from the queue backward
 @param[in] ctx points to an instance of queue structure
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_pull_back(a_que *ctx);
#define A_QUE_PULL_BACK(T, ctx) a_cast_s(T *, a_que_pull_back(ctx))

/*!
 @brief insert an element into the queue
 @param[in] ctx points to an instance of queue structure
 @param[in] idx index of element in this queue
  @arg 0 a_que_push_fore
  @arg n a_que_push_back
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_insert(a_que *ctx, a_size idx);
#define A_QUE_INSERT(T, ctx, idx) a_cast_s(T *, a_que_insert(ctx, idx))

/*!
 @brief remove an element from the queue
 @param[in] ctx points to an instance of queue structure
 @param[in] idx index of element in this queue
  @arg 0 a_que_pull_fore
  @arg n a_que_pull_back
 @return element pointer
  @retval 0 failure
*/
A_EXTERN void *a_que_remove(a_que *ctx, a_size idx);
#define A_QUE_REMOVE(T, ctx, idx) a_cast_s(T *, a_que_remove(ctx, idx))

#if defined(__cplusplus)
} /* extern "C" */
#endif /* __cplusplus */

/*!
 @brief iterate over a queue
 @code{.c}
 a_que_foreach(T, *, it, ctx)
 {
     assert(a_que_siz(ctx) >= sizeof(*it));
 }
 @endcode
 @param T the prefix of the element type
 @param P the suffix of the element type
 @param it the &a_que to use as a loop counter
 @param ctx points to an instance of queue structure
*/
#define a_que_foreach(T, P, it, ctx)                               \
    for (T P it = a_cast_r(T P, (ctx)->head_.next),                \
             P it##_ = a_cast_r(T P, a_list_(*, it)->next);        \
         a_list_(*, it) != &(ctx)->head_                           \
             ? ((void)(it = a_cast_r(T P, a_list_(*, it) + 1)), 1) \
             : (0);                                                \
         it = it##_, it##_ = a_cast_r(T P, a_list_(*, it)->next))

/*!
 @brief iterate over a queue in reverse
 @code{.c}
 a_que_foreach_reverse(T, *, it, ctx)
 {
     assert(a_que_siz(ctx) >= sizeof(*it));
 }
 @endcode
 @param T the prefix of the element type
 @param P the suffix of the element type
 @param it the &a_que to use as a loop counter
 @param ctx points to an instance of queue structure
*/
#define a_que_foreach_reverse(T, P, it, ctx)                       \
    for (T P it = a_cast_r(T P, (ctx)->head_.prev),                \
             P it##_ = a_cast_r(T P, a_list_(*, it)->prev);        \
         a_list_(*, it) != &(ctx)->head_                           \
             ? ((void)(it = a_cast_r(T P, a_list_(*, it) + 1)), 1) \
             : (0);                                                \
         it = it##_, it##_ = a_cast_r(T P, a_list_(*, it)->prev))

/*! @} a_que */

#endif /* a/que.h */