- Binary Search Tree functions
- Circular Buffer functions
- Filesystem related functions
- Geospatial related functions
- Hash Table functions
- JSON functions
- JSON Writer functions
- Miscellaneous functions
- Network related functions
- Quark (string to integer mapping) functions
- Queue functions
- Doubly linked list functions
- Singly linked list functions
- String functions
- Time related functions
A C library of miscellaneous functions that has no dependencies other than Glibc.
#define LIBAC_MAJOR_VERSION
#define LIBAC_MINOR_VERSION
#define LIBAC_MICRO_VERSION
typedef uint64_t u64
typedef int64_t s64
typedef uint32_t u32
typedef int32_t s32
typedef uint16_t u16
typedef int16_t s16
typedef uint8_t u8
typedef int8_t s8
typedef enum {
AC_HASH_ALGO_MD5 = 0,
AC_HASH_ALGO_SHA1,
AC_HASH_ALGO_SHA256,
AC_HASH_ALGO_SHA512
} ac_hash_algo_t;
typedef enum {
AC_SI_UNITS_NO,
AC_SI_UNITS_YES,
} ac_si_units_t;
#define AC_BYTE_BIT_SET(byte, bit)
#define AC_BYTE_BIT_CLR(byte, bit)
#define AC_BYTE_BIT_FLP(byte, bit)
#define AC_BYTE_BIT_TST(byte, bit)
#define AC_BYTE_NIBBLE_HIGH(byte)
#define AC_BYTE_NIBBLE_LOW(byte)
#define AC_LONG_TO_PTR(x)
#define AC_PTR_TO_LONG(p)
#define AC_MIN(a, b)
#define AC_MAX(a, b)
#define AC_ARRAY_SIZE(a)
#define AC_UUID4_LEN
#define __unused
#define __maybe_unused
#define __always_unused
These are aliases for __attribute__((unused))
#define __nonstring
This is an alias for __attribute__((nonstring))
#define AC_UUID4_LEN
These are a thin wrapper around the Glibc TSEARCH(3) set of binary tree functions.
typedef struct ac_btree {
void *rootp;
int (*compar)(const void *, const void *);
void (*free_node)(void *nodep);
} ac_btree_t;
void *ac_btree_new(int (*compar)(const void *, const void *),
void (*free_node)(void *nodep)):
void *ac_btree_add(ac_btree_t *tree, const void *key);
void *ac_btree_remove(ac_btree_t *tree, const void *key);
void *ac_btree_lookup(const ac_btree_t *tree, const void *key);
void ac_btree_foreach(const ac_btree_t *tree,
void (*action)(const void *nodep, VISIT which,
int depth));
void ac_btree_foreach(const ac_btree_t *tree,
void (*action)(const void *nodep, VISIT which,
void *data),
void *user_data);
bool ac_btree_is_empty(const ac_btree_t *tree);
void ac_btree_destroy(const ac_btree_t *tree);
typedef struct {
union {
void *cpy_buf;
void **ptr_buf;
} buf;
u32 head;
u32 tail;
u32 size;
u32 elem_sz;
int type;
} ac_circ_buf_t;
ac_circ_buf_t *ac_circ_buf_new(u32 size, u32 elem_sz);
u32 ac_circ_buf_count(const ac_circ_buf_t *cbuf);
int ac_circ_buf_pushm(ac_circ_buf_t *cbuf, void *buf, u32 count);
int ac_circ_buf_push(ac_circ_buf_t *cbuf, void *buf);
int ac_circ_buf_popm(ac_circ_buf_t *cbuf, void *buf, u32 count);
void *ac_circ_buf_pop(ac_circ_buf_t *cbuf);
void ac_circ_buf_foreach(const ac_circ_buf_t *cbuf,
void (*action)(void *item, void *data),
void *user_data);
void ac_circ_buf_reset(ac_circ_buf_t *cbuf);
void ac_circ_buf_destroy(const ac_circ_buf_t *cbuf);
#define AC_FS_AT_FDCWD AT_FDCWD
#define AC_FS_COPY_OVERWRITE 0x01
bool ac_fs_is_posix_name(const char *name);
int ac_fs_mkdir_p(int dirfd, const char *path, mode_t mode);
ssize_t ac_fs_copy(const char *from, const char *to, int flags);
typedef enum {
AC_GEO_EREF_WGS84 = 0,
AC_GEO_EREF_GRS80,
AC_GEO_EREF_AIRY1830
} ac_geo_ellipsoid_t;
typedef struct {
ac_geo_ellipsoid_t ref;
double lat;
double lon;
double alt;
double bearing;
double easting;
double northing;
} ac_geo_t;
typedef struct {
int degrees;
int minutes;
double seconds;
} ac_geo_dms_t;
void ac_geo_dd_to_dms(double degrees, ac_geo_dms_t *dms);
double ac_geo_dms_to_dd(const ac_geo_dms_t *dms);
double ac_geo_haversine(const ac_geo_t *from, const ac_geo_t *to);
void ac_geo_vincenty_direct(const ac_geo_t *from, ac_geo_t *to,
double distance);
ac_geo_bng_to_lat_lon - convert British National grid Eastings & Northings to latitude & longitude decimal degrees
void ac_geo_bng_to_lat_lon(ac_geo_t *geo);
ac_geo_lat_lon_to_bng - convert latitude & longitude decimal degrees to British National Grid Eastings & Northings
void ac_geo_lat_lon_to_bng(ac_geo_t *geo);
typedef struct {
struct ac_slist **buckets;
unsigned long count;
u32 (*hash_func)(const void *key);
int (*key_cmp)(const void *a, const void *b);
void (*free_key_func)(void *ptr);
void (*free_data_func)(void *ptr);
} ac_htable_t;
ac_htable_t *ac_htable_new(u32 (*hash_func)(const void *key),
int (*key_cmp)(const void *a, const void *b),
void (*free_key_func)(void *key),
void (*free_data_func)(void *data));
void ac_htable_insert(ac_htable_t *htable, void *key, void *data);
bool ac_htable_remove(ac_htable_t *htable, const void *key);
void *ac_htable_lookup(const ac_htable_t *htable, const void *key);
void ac_htable_foreach(const ac_htable_t *htable,
void (*action)(void *key, void *value,
void *user_data), void *user_data);
void ac_htable_destroy(const ac_htable_t *htable);
char *ac_json_load_from_fd(int fd, off_t offset);
char *ac_json_load_from_file(const char *file, off_t offset);
typedef struct {
char *str;
size_t len;
size_t allocated;
u8 depth;
bool skip_tabs;
char *indenter;
} ac_jsonw_t;
ac_jsonw_t *ac_jsonw_init(void);
void ac_jsonw_indent_sz(ac_jsonw_t *json, int size);
void ac_jsonw_set_indenter(ac_jsonw_t *json, const char *indenter);
void ac_jsonw_add_str(ac_jsonw_t *json, const char *name,
const char *value);
void ac_jsonw_add_int(ac_jsonw_t *json, const char *name, s64 value);
void ac_jsonw_add_real(ac_jsonw_t *json, const char *name, double value,
int dp);
void ac_jsonw_add_bool(ac_jsonw_t *json, const char *name, bool value);
void ac_jsonw_add_null(ac_jsonw_t *json, const char *name);
void ac_jsonw_add_str_or_null(ac_jsonw_t *json, const char *name,
const char *value);
void ac_jsonw_add_array(ac_jsonw_t *json, const char *name);
void ac_jsonw_end_array(ac_jsonw_t *json);
void ac_jsonw_add_object(ac_jsonw_t *json, const char *name);
void ac_jsonw_end_object(ac_jsonw_t *json);
void ac_jsonw_end(ac_jsonw_t *json);
void ac_jsonw_free(const ac_jsonw_t *json);
size_t ac_jsonw_len(const ac_jsonw_t *json);
const char *ac_jsonw_get(const ac_jsonw_t *json);
typedef struct crypt_data ac_crypt_data_t;
typedef enum {
AC_MISC_PPB_BYTES = 0,
AC_MISC_PPB_KBYTES,
AC_MISC_PPB_MBYTES,
AC_MISC_PPB_GBYTES,
AC_MISC_PPB_TBYTES,
AC_MISC_PPB_PBYTES,
AC_MISC_PPB_EBYTES
} ac_misc_ppb_factor_t;
typedef enum {
AC_MISC_SHUFFLE_FISHER_YATES = 0
} ac_misc_shuffle_t;
typedef struct {
ac_misc_ppb_factor_t factor;
const char *prefix;
union {
u16 v_u16;
float v_float;
} value;
} ac_misc_ppb_t;
void ac_misc_ppb(u64 bytes, ac_si_units_t si, ac_misc_ppb_t *ppb);
char *ac_misc_passcrypt(const char *pass, ac_hash_algo_t hash_type,
ac_crypt_data_t *data);
const char *ac_misc_gen_uuid4(char *dst);
bool ac_misc_luhn_check(u64 num);
int ac_misc_shuffle(void *base, size_t nmemb, size_t size,
ac_misc_shuffle_t algo);
u32 ac_hash_func_str(const void *key);
u32 ac_hash_func_u32(const void *key);
u32 ac_hash_func_ptr(const void *key);
int ac_cmp_ptr(const void *a, const void *b};
int ac_cmp_str(const void *a, const void *b);
int ac_cmp_u32(const void *a, const void *b);
int ac_net_port_from_sa(const struct sockaddr *sa);
int ac_net_inet_pton(const char *src, void *dst);
const char *ac_net_inet_ntop(const void *src, char *dst, socklen_t size);
int ac_net_ns_lookup_by_host(const struct addrinfo *hints,
const char *node,
bool (*ac_ns_lookup_cb)
(const struct addrinfo *ai,
const char *res));
int ac_net_ns_lookup_by_ip(const struct addrinfo *hints,
const char *node,
bool (*ac_ns_lookup_cb)
(const struct addrinfo *ai,
const char *res));
bool ac_net_ipv4_isin(const char *network, u8 cidr, const char *addr);
bool ac_net_ipv4_isin_sa(const char *network, u8 cidr,
const struct sockaddr *sa);
bool ac_net_ipv6_isin(const char *network, u8 prefixlen, const char *addr);
bool ac_net_ipv6_isin_sa(const char *network, u8 prefixlen,
const struct sockaddr *sa);
typedef struct {
struct ac_btree *qt;
void **quarks;
int last;
void (*free_func)(void *ptr);
} ac_quark_t;
void ac_quark_init(ac_quark_t *quark, void(*free_func)(void *ptr));
int ac_quark_from_string(ac_quark_t *quark, const char *str);
const char *ac_quark_to_string(const ac_quark_t *quark, int id);
void ac_quark_destroy(const ac_quark_t *quark);
typedef struct {
struct ac_slist *queue;
struct ac_slist *tail;
u32 items;
void (*free_func)(void *item);
} ac_queue_t;
ac_queue_t *ac_queue_new(void);
int ac_queue_push(ac_queue_t *queue, void *item);
void *ac_queue_pop(ac_queue_t *queue);
void ac_queue_foreach(const ac_queue_t *queue,
void (*action)(void *item, void *data),
void *user_data);
u32 ac_queue_nr_items(const ac_queue_t *queue);
void ac_queue_destroy(const ac_queue_t *queue, (*free_func)(void *item));
typedef struct ac_list {
void *data;
struct ac_list *prev;
struct ac_list *next;
} ac_list_t;
ac_list_t *ac_list_last(ac_list_t *list);
long ac_list_len(const ac_list_t *list);
void ac_list_add(ac_list_t **list, void *data);
void ac_list_preadd(ac_list_t **list, void *data);
bool ac_list_remove(ac_list_t **list, void *data,
void (*free_data)(void *data));
bool ac_list_remove_nth(ac_list_t **list, long n,
void (*free_data)(void *data));
bool ac_list_remove_custom(ac_list_t **list, void *data,
int (*compar)(const void *a, const void *b),
void (*free_data)(void *data));
void ac_list_reverse(ac_list_t **list);
ac_list_t *ac_list_find(ac_list_t *list, const void *data);
ac_list_t *ac_list_find_custom(ac_list_t *list, const void *data,
int (*compar)(const void *a,
const void *b));
void *ac_list_nth_data(ac_list_t *list, long n)
void ac_list_foreach(ac_list_t *list,
void (*action)(void *item, void *data),
void *user_data);
void ac_list_rev_foreach(ac_list_t *list,
void (*action)(void *item, void *data),
void *user_data);
void ac_list_destroy(ac_list_t **list, void (*free_data)(void *data));
typedef struct ac_slist {
void *data;
struct ac_slist *next;
} ac_slist_t;
ac_slist_t *ac_slist_last(ac_slist_t *list);
long ac_slist_len(const ac_slist_t *list);
void ac_slist_add(ac_slist_t **list, void *data);
void ac_slist_preadd(ac_slist_t **list, void *data);
bool ac_slist_remove(ac_slist_t **list, void *data, void (*free_data)
(void *data));
bool ac_slist_remove_nth(ac_slist_t **list, long n, void (*free_data)
(void *data));
bool ac_slist_remove_custom(ac_slist_t **list, void *data,
int (*compar)(const void *a, const void *b),
void (*free_data)(void *data));
void ac_slist_reverse(ac_slist_t **list);
ac_slist_t *ac_slist_find(ac_slist_t *list, const void *data);
ac_slist_t *ac_slist_find_custom(ac_slist_t *list, const void *data,
int (*compar)(const void *a,
const void *b));
void *ac_slist_nth_data(ac_slist_t *list, long n);
void ac_slist_foreach(ac_slist_t *list,
void (*action)(void *item, void *data),
void *user_data);
void ac_slist_destroy(ac_slist_t **list, void (*free_data)(void *data));
#define AC_STR_SPLIT_ALWAYS 0x00
#define AC_STR_SPLIT_STRICT 0x01
void ac_str_freev(char **stringv);
char **ac_str_split(const char *string, int delim, int flags);
char *ac_str_chomp(char *string);
char *ac_str_substr(const char *src, char *dest, size_t start, size_t len);
int ac_str_levenshtein(const char *s, const char *t);
/*
* Define a second, millisecond and microsecond in terms of nanoseconds.
*/
#define AC_TIME_NS_SEC 1000000000L
#define AC_TIME_NS_MSEC 1000000L
#define AC_TIME_NS_USEC 1000L
double ac_time_tspec_diff(struct timespec *delta,
const struct timespec *end,
const struct timespec *start);
void ac_time_secs_to_hms(long total, int *hours, int *minutes,
int *seconds);
int ac_time_nsleep(u64 nsecs);
libac is primarily developed under Linux but it also builds and runs under FreeBSD.
The simplest way is to build the rpm by simply doing
$ make rpm
in the repository root. It just needs a suitable rpmbuild/ directory structure which can be created with
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
and the rpmbuild tool which can be found in the rpm-build package.
libac has a single dependency on FreeBSD of libuuid, it also needs to be built with gmake (GNU make), these can be installed with
$ sudo pkg install e2fsprogs-libuuid gmake
then libac can be built with
$ gmake
or if you don’t have GCC installed
$ gmake CC=clang
Just
#include <libac.h>
in your program and link with -lac assuming you’ve built and installed the RPM or similar.
See src/test.c for examples on using the above.
libac is intended to be thread-safe.
This library is licensed under the GNU Lesser General Public License (LGPL) version 2.1
See COPYING in the repository root for details.
See CodingStyle.rst & Contributing.rst
Andrew Clayton <ac@sigsegv.uk>