#ifndef LIBA_BUF_H
#define LIBA_BUF_H
#include "a.h"
typedef struct a_buf
{
void *ptr_;
a_size siz_;
a_size num_;
a_size mem_;
} a_buf;
A_INTERN void *a_buf_ptr(a_buf const *ctx) { return ctx->ptr_; }
#define A_BUF_PTR(T, ctx) a_cast_s(T *, a_buf_ptr(ctx))
A_INTERN a_size a_buf_siz(a_buf const *ctx) { return ctx->siz_; }
A_INTERN a_size a_buf_num(a_buf const *ctx) { return ctx->num_; }
A_INTERN a_size a_buf_mem(a_buf const *ctx) { return ctx->mem_; }
A_INTERN void *a_buf_at_(a_buf const *ctx, a_size idx)
{
return a_byte_(*, ctx->ptr_) + ctx->siz_ * idx;
}
#define A_BUF_AT_(T, ctx, idx) a_cast_s(T *, a_buf_at_(ctx, idx))
A_INTERN void *a_buf_at(a_buf const *ctx, a_size idx)
{
return idx < ctx->mem_ ? a_buf_at_(ctx, idx) : A_NULL;
}
#define A_BUF_AT(T, ctx, idx) a_cast_s(T *, a_buf_at(ctx, idx))
A_INTERN void *a_buf_idx(a_buf const *ctx, a_diff idx)
{
a_size const num = idx >= 0 ? a_size_c(idx) : a_size_c(idx) + ctx->num_;
return num < ctx->mem_ ? a_buf_at_(ctx, num) : A_NULL;
}
#define A_BUF_IDX(T, ctx, idx) a_cast_s(T *, a_buf_idx(ctx, idx))
A_INTERN void *a_buf_top_(a_buf const *ctx)
{
return a_byte_(*, ctx->ptr_) + ctx->siz_ * (ctx->num_ - 1);
}
#define A_BUF_TOP_(T, ctx) a_cast_s(T *, a_buf_top_(ctx))
A_INTERN void *a_buf_top(a_buf const *ctx)
{
return ctx->num_ ? a_buf_top_(ctx) : A_NULL;
}
#define A_BUF_TOP(T, ctx) a_cast_s(T *, a_buf_top(ctx))
A_INTERN void *a_buf_end(a_buf const *ctx)
{
return a_byte_(*, ctx->ptr_) + ctx->siz_ * ctx->num_;
}
#define A_BUF_END(T, ctx) a_cast_s(T *, a_buf_end(ctx))
#if defined(__cplusplus)
extern "C" {
#endif
A_EXTERN void a_buf_ctor(a_buf *ctx, void *ptr, a_size siz, a_size num);
A_EXTERN void a_buf_dtor(a_buf *ctx, void (*dtor)(void *));
A_EXTERN void a_buf_move(a_buf *ctx, a_buf *obj);
A_EXTERN void a_buf_drop(a_buf *ctx, void (*dtor)(void *));
A_EXTERN void a_buf_swap(a_buf const *ctx, a_size lhs, a_size rhs);
A_EXTERN void a_buf_sort(a_buf const *ctx, int (*cmp)(void const *, void const *));
A_EXTERN void a_buf_sort_fore(a_buf const *ctx, int (*cmp)(void const *, void const *));
A_EXTERN void a_buf_sort_back(a_buf const *ctx, int (*cmp)(void const *, void const *));
A_EXTERN void *a_buf_push_sort(a_buf *ctx, void const *key, int (*cmp)(void const *, void const *));
#define A_BUF_PUSH_SORT(T, ctx, key, cmp) a_cast_s(T *, a_buf_push_sort(ctx, key, cmp))
A_EXTERN void *a_buf_search(a_buf const *ctx, void const *obj, int (*cmp)(void const *, void const *));
#define A_BUF_SEARCH(T, ctx, obj, cmp) a_cast_s(T *, a_buf_search(ctx, obj, cmp))
A_EXTERN void *a_buf_insert(a_buf *ctx, a_size idx);
#define A_BUF_INSERT(T, ctx, idx) a_cast_s(T *, a_buf_insert(ctx, idx))
A_EXTERN void *a_buf_remove(a_buf *ctx, a_size idx);
#define A_BUF_REMOVE(T, ctx, idx) a_cast_s(T *, a_buf_remove(ctx, idx))
A_EXTERN void *a_buf_push_fore(a_buf *ctx);
#define A_BUF_PUSH_FORE(T, ctx) a_cast_s(T *, a_buf_push_fore(ctx))
A_EXTERN void *a_buf_push_back(a_buf *ctx);
#define A_BUF_PUSH_BACK(T, ctx) a_cast_s(T *, a_buf_push_back(ctx))
A_EXTERN void *a_buf_pull_fore(a_buf *ctx);
#define A_BUF_PULL_FORE(T, ctx) a_cast_s(T *, a_buf_pull_fore(ctx))
A_EXTERN void *a_buf_pull_back(a_buf *ctx);
#define A_BUF_PULL_BACK(T, ctx) a_cast_s(T *, a_buf_pull_back(ctx))
#if defined(__cplusplus)
}
#endif
A_INTERN void *a_buf_push(a_buf *ctx) { return a_buf_push_back(ctx); }
#define A_BUF_PUSH(T, ctx) a_cast_s(T *, a_buf_push(ctx))
A_INTERN void *a_buf_pull(a_buf *ctx) { return a_buf_pull_back(ctx); }
#define A_BUF_PULL(T, ctx) a_cast_s(T *, a_buf_pull(ctx))
#define a_buf_forenum(i, ctx) a_forenum(a_size, i, (ctx)->num_)
#define a_buf_forenum_reverse(i, ctx) a_forenum_reverse(a_size, i, (ctx)->num_)
#define a_buf_foreach(T, P, it, ctx) a_foreach(T, P, it, (ctx)->ptr_, (ctx)->num_)
#define a_buf_foreach_reverse(T, P, it, ctx) a_foreach_reverse(T, P, it, (ctx)->ptr_, (ctx)->num_)
#endif