liba 0.1.15

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

#ifndef LIBA_BUF_H
#define LIBA_BUF_H

#include "a.h"

/*!
 @ingroup liba
 @addtogroup a_buf basic buffer library
 @{
*/

/*!
 @brief instance structure for basic buffer
*/
typedef struct a_buf
{
    void *ptr_; /*!< address of memory */
    a_size siz_; /*!< size of a element */
    a_size num_; /*!< number of element */
    a_size mem_; /*!< memory of element */
} a_buf;

/*!
 @brief access address of buffer for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
*/
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))

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

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

/*!
 @brief access memory of element for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
*/
A_INTERN a_size a_buf_mem(a_buf const *ctx) { return ctx->mem_; }

/*!
 @brief access specified element for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @param[in] idx index of element less than memory
 @note should check for out of bounds
 @return specified element pointer
*/
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))

/*!
 @brief access specified element for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @param[in] idx index of element less than memory
 @return specified element pointer
  @retval 0 out of bounds
*/
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))

/*!
 @brief access specified element for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @param[in] idx index of element -memory < idx < memory
 @return specified element pointer
  @retval 0 out of bounds
*/
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))

/*!
 @brief access top element for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @note should check if buffer is empty
 @return specified element pointer
*/
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))

/*!
 @brief access top element for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @return specified element pointer
  @retval 0 empty buffer
*/
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))

/*!
 @brief access end pointer for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @return buffer end pointer
*/
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 /* __cplusplus */

/*!
 @brief constructor for buffer structure
 @param[in] ctx points to an instance of buffer structure
 @param[in] ptr address of memory
 @param[in] siz size of a element
 @param[in] num number of element
*/
A_EXTERN void a_buf_ctor(a_buf *ctx, void *ptr, a_size siz, a_size num);

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

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

/*!
 @brief drop all the elements for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @param[in] dtor current element destructor
*/
A_EXTERN void a_buf_drop(a_buf *ctx, void (*dtor)(void *));

/*!
 @brief swap elements lhs and rhs for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer structure
 @param[in] lhs element index on the left
 @param[in] rhs element index on the right
*/
A_EXTERN void a_buf_swap(a_buf const *ctx, a_size lhs, a_size rhs);

/*!
 @brief sort all elements for a pointer to buffer structure
 @param[in] ctx points to an instance of buffer 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_buf_sort(a_buf const *ctx, int (*cmp)(void const *, void const *));

/*!
 @brief insert sort foremost element for a pointer to buffer structure
 @code{.c}
 T *obj = A_BUF_PUSH_FORE(T, ctx);
 if (obj)
 {
     CTOR(obj);
     INIT(obj);
     a_buf_sort_fore(ctx, cmp);
 }
 @endcode
 @param[in] ctx points to an instance of buffer 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_buf_sort_fore(a_buf const *ctx, int (*cmp)(void const *, void const *));

/*!
 @brief insert sort backmost element for a pointer to buffer structure
 @code{.c}
 T *obj = A_BUF_PUSH_BACK(T, ctx);
 if (obj)
 {
     CTOR(obj);
     INIT(obj);
     a_buf_sort_back(ctx, cmp);
 }
 @endcode
 @param[in] ctx points to an instance of buffer 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_buf_sort_back(a_buf const *ctx, int (*cmp)(void const *, void const *));

/*!
 @brief push an element into the buffer and sort it
 @param[in] ctx points to an instance of buffer 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_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))

/*!
 @brief search the given element in this buffer
 @param[in] ctx points to an instance of buffer structure
 @param[in] obj object that serves as key for the search
 @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 matching element pointer
  @retval 0 failure
*/
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))

/*!
 @brief insert an element into the buffer
 @param[in] ctx points to an instance of buffer structure
 @param[in] idx index of element in this buffer
  @arg 0 a_buf_push_fore
  @arg n a_buf_push_back
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief remove an element from the buffer
 @param[in] ctx points to an instance of buffer structure
 @param[in] idx index of element in this buffer
  @arg 0 a_buf_pull_fore
  @arg n a_buf_pull_back
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief push an element into the buffer forward
 @param[in] ctx points to an instance of buffer structure
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief push an element into the buffer backward
 @param[in] ctx points to an instance of buffer structure
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief pull an element from the buffer forward
 @param[in] ctx points to an instance of buffer structure
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief pull an element from the buffer backward
 @param[in] ctx points to an instance of buffer structure
 @return element pointer
  @retval 0 failure
*/
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)
} /* extern "C" */
#endif /* __cplusplus */

/*!
 @brief push an element into the buffer
 @param[in] ctx points to an instance of buffer structure
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief pull an element from the buffer
 @param[in] ctx points to an instance of buffer structure
 @return element pointer
  @retval 0 failure
*/
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))

/*!
 @brief iterate over a buffer
 @code{.c}
 a_buf_forenum(i, ctx)
 {
     T *it = (T *)a_buf_at(ctx, i);
     assert(a_buf_siz(ctx) == sizeof(*it));
 }
 @endcode
 @param i index of elements in the buffer
 @param ctx points to an instance of buffer structure
*/
#define a_buf_forenum(i, ctx) a_forenum(a_size, i, (ctx)->num_)

/*!
 @brief iterate over a buffer in reverse
 @code{.c}
 a_buf_forenum_reverse(i, ctx)
 {
     T *it = (T *)a_buf_at(ctx, i);
     assert(a_buf_siz(ctx) == sizeof(*it));
 }
 @endcode
 @param i index of elements in the buffer
 @param ctx points to an instance of buffer structure
*/
#define a_buf_forenum_reverse(i, ctx) a_forenum_reverse(a_size, i, (ctx)->num_)

/*!
 @brief iterate over a buffer
 @code{.c}
 a_buf_foreach(T, *, it, ctx)
 {
     assert(a_buf_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_buf to use as a loop counter
 @param ctx points to an instance of buffer structure
*/
#define a_buf_foreach(T, P, it, ctx) a_foreach(T, P, it, (ctx)->ptr_, (ctx)->num_)

/*!
 @brief iterate over a buffer in reverse
 @code{.c}
 a_buf_foreach_reverse(T, *, it, ctx)
 {
     assert(a_buf_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_buf to use as a loop counter
 @param ctx points to an instance of buffer structure
*/
#define a_buf_foreach_reverse(T, P, it, ctx) a_foreach_reverse(T, P, it, (ctx)->ptr_, (ctx)->num_)

/*! @} a_buf */

#endif /* a/buf.h */