tabular

Flexible input tabulator
git clone https://git.sinitax.com/sinitax/tabular
Log | Files | Refs | Submodules | sfeed.txt

dvec.h (4568B)


      1#pragma once
      2
      3#include "allocator.h"
      4
      5#include <sys/types.h>
      6#include <limits.h>
      7#include <stdbool.h>
      8#include <stdint.h>
      9#include <stddef.h>
     10
     11#define DVEC_ERRNO(rc) ((rc) > 0 && (rc) & (1 << 30) ? (rc) & ~(1 << 30) : 0)
     12#define DVEC_ERR(lut, rc) errx(1, "libdvec: %s", \
     13	(rc) == DVEC_BAD ? lut[0] : (DVEC_ERRNO(rc) ? strerror(DVEC_ERRNO(rc)) : lut[rc+1]))
     14
     15#define DVEC_ITER(dvec, p)     (p) = NULL; ((p) = dvec_iter_fwd((dvec), (p)));
     16#define DVEC_ITER_BWD(dvec, p) (p) = NULL; ((p) = dvec_iter_bwd((dvec), (p)));
     17
     18#define DVEC_STRERR_INIT \
     19	[0] = "Failure", \
     20	[1+DVEC_OK] = "Success", \
     21	[1+DVEC_LOCKED] = "Locked", \
     22	[1+DVEC_MODIFIED] = "Modified"
     23
     24#ifdef LIBDVEC_ASSERT_ARGS
     25#include "stdlib.h"
     26#define LIBDVEC_ABORT_ON_ARGS(cond) do { if (cond) abort(); } while (0)
     27#else
     28#define LIBDVEC_ABORT_ON_ARGS(cond)
     29#endif
     30
     31#ifdef LIBDVEC_ASSERT_ALLOC
     32#include "stdlib.h"
     33#define LIBDVEC_ABORT_ON_ALLOC(cond) do { if (cond) abort(); } while (0)
     34#else
     35#define LIBDVEC_ABORT_ON_ALLOC(cond)
     36#endif
     37
     38enum {
     39	DVEC_BAD = -1 & INT_MAX,
     40	DVEC_OK = 0,
     41	DVEC_LOCKED = 1 << 0,
     42	DVEC_MODIFIED = 1 << 1
     43};
     44
     45struct dvec {
     46	size_t dsize;
     47	size_t len, cap;
     48	uint8_t *data;
     49	uint8_t locked : 1; /* prevents resizes */
     50	uint8_t fused : 1; /* single allocation w/ data */
     51	const struct allocator *allocator;
     52};
     53
     54typedef bool (*dvec_sort_order_fn)(const void *left, const void *right, const void *user);
     55typedef int (*dvec_search_cmp_fn)(const void *other, const void *user);
     56
     57int dvec_init(struct dvec *dvec, size_t dsize, size_t cap,
     58	const struct allocator *allocator);
     59int dvec_deinit(struct dvec *dvec);
     60
     61struct dvec *dvec_alloc(size_t dsize, size_t cap,
     62	const struct allocator *allocator, int *rc);
     63struct dvec *dvec_alloc_fused(size_t dsize, size_t cap,
     64	const struct allocator *allocator, int *rc);
     65int dvec_free(struct dvec *dvec);
     66
     67int dvec_copy(struct dvec *dst, struct dvec *src);
     68void dvec_move(struct dvec *dst, struct dvec *src);
     69void dvec_swap(struct dvec *dst, struct dvec *src);
     70
     71void dvec_clear(struct dvec *dvec);
     72int dvec_reserve(struct dvec *dvec, size_t cap);
     73int dvec_shrink(struct dvec *dvec);
     74
     75int dvec_add(struct dvec *dvec, size_t index, size_t count);
     76void dvec_rm(struct dvec *dvec, size_t index, size_t count);
     77void dvec_replace(struct dvec *dvec, size_t index,
     78	const void *data, size_t count);
     79
     80void *dvec_iter_fwd(const struct dvec *dvec, const void *p);
     81void *dvec_iter_bwd(const struct dvec *dvec, const void *p);
     82
     83int dvec_quick_sort(struct dvec *dvec, const struct allocator *allocator,
     84	void *tmp, bool reverse, dvec_sort_order_fn in_order, const void *user);
     85int dvec_quick_sort_ex(struct dvec *dvec, const struct allocator *allocator,
     86	void *tmp, bool reverse, dvec_sort_order_fn in_order, const void *user);
     87
     88ssize_t dvec_binary_search(struct dvec *dvec, dvec_search_cmp_fn search_cmp,
     89	void *user, ssize_t *lower, ssize_t *higher);
     90
     91static inline void *
     92dvec_at(const struct dvec *dvec, size_t index)
     93{
     94	LIBDVEC_ABORT_ON_ARGS(!dvec || index >= dvec->len);
     95
     96	return dvec->data + index * dvec->dsize;
     97}
     98
     99static inline void *
    100dvec_at_back(const struct dvec *dvec, size_t index)
    101{
    102	LIBDVEC_ABORT_ON_ARGS(!dvec || !index || index >= dvec->len);
    103
    104	return dvec->data + (dvec->len  - 1 - index) * dvec->dsize;
    105}
    106
    107static inline void *
    108dvec_front(const struct dvec *dvec)
    109{
    110	LIBDVEC_ABORT_ON_ARGS(!dvec);
    111
    112	return dvec->data;
    113}
    114
    115static inline void *
    116dvec_back(const struct dvec *dvec)
    117{
    118	LIBDVEC_ABORT_ON_ARGS(!dvec);
    119
    120	return dvec->data + (dvec->len - 1) * dvec->dsize;
    121}
    122
    123static inline bool
    124dvec_empty(const struct dvec *dvec)
    125{
    126	LIBDVEC_ABORT_ON_ARGS(!dvec);
    127
    128	return !dvec->len;
    129}
    130
    131static inline size_t
    132dvec_len(const struct dvec *dvec)
    133{
    134	LIBDVEC_ABORT_ON_ARGS(!dvec);
    135
    136	return dvec->len;
    137}
    138
    139static inline int
    140dvec_add_back(struct dvec *dvec, size_t count)
    141{
    142	return dvec_add(dvec, dvec->len, count);
    143}
    144
    145static inline void
    146dvec_rm_back(struct dvec *dvec, size_t count)
    147{
    148	dvec_rm(dvec, dvec->len - count, count);
    149}
    150
    151static inline void
    152dvec_lock(struct dvec *dvec, bool lock)
    153{
    154	dvec->locked = lock;
    155}
    156
    157static inline void *
    158dvec_push(struct dvec *dvec)
    159{
    160	LIBDVEC_ABORT_ON_ARGS(!dvec);
    161
    162	dvec_reserve(dvec, dvec->len + 1);
    163
    164	return dvec->data + dvec->len++ * dvec->dsize;
    165}
    166
    167static inline void *
    168dvec_pop(struct dvec *dvec)
    169{
    170	LIBDVEC_ABORT_ON_ARGS(!dvec || !dvec->len);
    171
    172	return dvec->data + --dvec->len * dvec->dsize;
    173}
    174
    175static inline size_t
    176dvec_idx(struct dvec *dvec, const void *p)
    177{
    178	LIBDVEC_ABORT_ON_ARGS(!dvec || p < dvec->data
    179		|| p >= dvec->data + dvec->dsize * dvec->len);
    180
    181	return (size_t) ((uint8_t *)p - dvec->data) / dvec->dsize;
    182}