#ifndef LIBA_QUE_H
#define LIBA_QUE_H
#include "list.h"
typedef struct a_que
{
a_list head_;
a_list **ptr_;
a_size siz_;
a_size num_;
a_size cur_;
a_size mem_;
} a_que;
A_INTERN a_size a_que_siz(a_que const *ctx) { return ctx->siz_; }
A_INTERN a_size a_que_num(a_que const *ctx) { return ctx->num_; }
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))
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))
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))
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))
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
A_EXTERN a_que *a_que_new(a_size size);
A_EXTERN void a_que_die(a_que *ctx, void (*dtor)(void *));
A_EXTERN void a_que_ctor(a_que *ctx, a_size size);
A_EXTERN void a_que_dtor(a_que *ctx, void (*dtor)(void *));
A_EXTERN void a_que_move(a_que *ctx, a_que *obj);
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))
A_EXTERN int a_que_drop(a_que *ctx, void (*dtor)(void *));
A_EXTERN int a_que_edit(a_que *ctx, a_size size, void (*dtor)(void *));
A_EXTERN int a_que_swap(a_que const *ctx, a_size lhs, a_size rhs);
A_EXTERN void a_que_sort_fore(a_que const *ctx, int (*cmp)(void const *, void const *));
A_EXTERN void a_que_sort_back(a_que const *ctx, int (*cmp)(void const *, void const *));
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))
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))
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))
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))
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))
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))
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)
}
#endif
#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))
#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))
#endif