{"id":20181395,"url":"https://github.com/ac000/libac","last_synced_at":"2025-09-21T17:32:18.979Z","repository":{"id":19857571,"uuid":"87969694","full_name":"ac000/libac","owner":"ac000","description":"A C library of miscellaneous utility functions","archived":false,"fork":false,"pushed_at":"2024-12-21T04:55:35.000Z","size":329,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-21T05:25:25.124Z","etag":null,"topics":["c","data-structures","freebsd","geospatial","json","linux","network-programming","string-distance","time"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ac000.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"Contributing.md","funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-11T19:06:30.000Z","updated_at":"2024-12-21T04:55:39.000Z","dependencies_parsed_at":"2023-09-30T01:04:25.160Z","dependency_job_id":null,"html_url":"https://github.com/ac000/libac","commit_stats":null,"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ac000%2Flibac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ac000%2Flibac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ac000%2Flibac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ac000%2Flibac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ac000","download_url":"https://codeload.github.com/ac000/libac/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233778901,"owners_count":18728846,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","data-structures","freebsd","geospatial","json","linux","network-programming","string-distance","time"],"created_at":"2024-11-14T02:35:24.487Z","updated_at":"2025-09-21T17:32:13.675Z","avatar_url":"https://github.com/ac000.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libac\n\n[![Builds](https://github.com/ac000/libac/actions/workflows/build_tests.yaml/badge.svg)](https://github.com/ac000/libac/actions/workflows/build_tests.yaml \"GitHub workflow builds\")\n[![FreeBSD Build Status](https://api.cirrus-ci.com/github/ac000/libac.svg)](https://cirrus-ci.com/github/ac000/libac \"Cirrus FreeBSD builds\")\n[![CodeQL](https://github.com/ac000/libac/workflows/CodeQL/badge.svg)](https://github.com/ac000/libac/actions?query=workflow:CodeQL \"Code quality workflow status\")\n\n1. [Overview](#overview)\n2. [Types, defines, etc](#types-defines-etc)\n  * [Library version](#library-version)\n  * [Types](#types)\n  * [ac\\_geo\\_ellipsoid\\_t](#ac_geo_ellipsoid_t)\n  * [ac\\_hash\\_algo\\_t](#ac_hash_algo_t)\n  * [ac\\_misc\\_ppb\\_factor\\_t](#ac_misc_ppb_factor_t)\n  * [ac\\_si\\_units\\_t](#ac_si_units_t)\n  * [misc](#misc)\n3. [Functions](#functions)\n  * [Binary Search Tree functions](#binary-search-tree-functions)\n  * [Circular Buffer functions](#circular-buffer-functions)\n  * [Filesystem related functions](#filesystem-related-functions)\n  * [Geospatial related functions](#geospatial-related-functions)\n  * [Hash Table functions](#hash-table-functions)\n  * [JSON functions](#json-functions)\n  * [JSON Writer functions](#json-writer-functions)\n  * [Miscellaneous functions](#miscellaneous-functions)\n  * [Network related functions](#network-related-functions)\n  * [Quark (string to integer mapping) functions](#quark-functions)\n  * [Queue functions](#queue-functions)\n  * [Doubly linked list functions](doubly-linked-list-functions)\n  * [Singly linked list functions](#singly-linked-list-functions)\n  * [String functions](#string-functions)\n  * [Time related functions](#time-related-functions)\n4. [Build it](#build-it)\n5. [How to use](#how-to-use)\n6. [License](#license)\n7. [Contributing](#contributing)\n\n## Overview\n\nA C library of miscellaneous functions that has no dependencies other than\nGlibc.\n\n\n## Types, defines, etc\n\n### Library version\n\n    #define LIBAC_MAJOR_VERSION\n    #define LIBAC_MINOR_VERSION\n    #define LIBAC_MICRO_VERSION\n\n### Types\n\n    typedef uint64_t u64\n    typedef int64_t  s64\n    typedef uint32_t u32\n    typedef int32_t  s32\n    typedef uint16_t u16\n    typedef int16_t  s16\n    typedef uint8_t   u8\n    typedef int8_t    s8\n\n    typedef struct crypt_data ac_crypt_data_t\n\n### ac\\_geo\\_ellipsoid\\_t\n\n    AC_GEO_EREF_WGS84\n    AC_GEO_EREF_GRS80\n    AC_GEO_EREF_AIRY1830\n\n### ac\\_hash\\_algo\\_t\n\n    AC_HASH_ALGO_MD5\n    AC_HASH_ALGO_SHA1\n    AC_HASH_ALGO_SHA256\n    AC_HASH_ALGO_SHA512\n\n### ac\\_misc\\_ppb\\_factor\\_t\n\n    AC_MISC_PPB_BYTES\n    AC_MISC_PPB_KBYTES\n    AC_MISC_PPB_MBYTES\n    AC_MISC_PPB_GBYTES\n    AC_MISC_PPB_TBYTES\n    AC_MISC_PPB_PBYTES\n    AC_MISC_PPB_EBYTES\n\n### ac\\_misc\\_shuffle\\_t\n\n    AC_MISC_SHUFFLE_FISHER_YATES\n\n### ac\\_si\\_units\\_t\n\n    AC_SI_UNITS_NO\n    AC_SI_UNITS_YES\n\n### Macros\n\n    AC_BYTE_BIT_SET(byte, bit)\n    AC_BYTE_BIT_CLR(byte, bit)\n    AC_BYTE_BIT_FLP(byte, bit)\n    AC_BYTE_BIT_TST(byte, bit)\n    AC_BYTE_NIBBLE_HIGH(byte)\n    AC_BYTE_NIBBLE_LOW(byte)\n\n    AC_LONG_TO_PTR(x)\n    AC_PTR_TO_LONG(p)\n\n    AC_MIN(a, b)\n    AC_MAX(a, b)\n\n    AC_ARRAY_SIZE(a)\n\n### misc\n\n    #define __unused\n    #define __maybe_unused\n    #define __always_unused\n\nThese are aliases for \\_\\_attribute\\_\\_((unused))\n\n    #define AC_FS_COPY_OVERWRITE\n\n    #define AC_UUID4_LEN\t36\n\n    #define AC_STR_SPLIT_ALWAYS\n    #define AC_STR_SPLIT_STRICT\n\n    #define AC_TIME_NS_SEC\n    #define AC_TIME_NS_MSEC\n    #define AC_TIME_NS_USEC\n\n\n## Functions\n\n### Binary Search Tree functions\n\nThese are a thin wrapper around the Glibc TSEARCH(3) set of binary tree\nfunctions.\n\n#### ac\\_btree\\_new - create a new binary tree\n\n    void *ac_btree_new(int (*compar)(const void *, const void *),\n                       void (*free_node)(void *nodep)):\n\n#### ac\\_btree\\_add - add a node to the tree\n\n    void *ac_btree_add(ac_btree_t *tree, const void *key);\n\n#### ac\\_btree\\_remove - remove a node from the tree\n\n    void *ac_btree_remove(ac_btree_t *tree, const void *key);\n\n#### ac\\_btree\\_lookup - lookup a node in the tree\n\n    void *ac_btree_lookup(const ac_btree_t *tree, const void *key);\n\n#### ac\\_btree\\_foreach - iterate over the tree\n\n    void ac_btree_foreach(const ac_btree_t *tree,\n                          void (*action)(const void *nodep, VISIT which,\n                                         int depth));\n\n#### ac\\_btree\\_foreach\\_data - iterate over the tree with user\\_data\n\n    void ac_btree_foreach(const ac_btree_t *tree,\n                          void (*action)(const void *nodep, VISIT which,\n                                         void *data),\n                          void *user_data);\n\n#### ac\\_btree\\_is\\_empty - test if the binary tree is empty\n\n    bool ac_btree_is_empty(const ac_btree_t *tree);\n\n#### ac\\_btree\\_destroy - destroy a binary tree freeing all memory\n\n    void ac_btree_destroy(const ac_btree_t *tree);\n\n\n### Circular Buffer functions\n\n#### ac\\_circ\\_buf\\_new - create a new circular buffer (size must be power of 2)\n\n    ac_circ_buf_t *ac_circ_buf_new(u32 size, u32 elem_sz);\n\n#### ac\\_circ\\_buf\\_count - how many items are in the buffer\n\n    u32 ac_circ_buf_count(const ac_circ_buf_t *cbuf);\n\n#### ac\\_circ\\_buf\\_pushm - push multiple items into the buffer\n\n    int ac_circ_buf_pushm(ac_circ_buf_t *cbuf, void *buf, u32 count);\n\n#### ac\\_circ\\_buf\\_push - push an item into the buffer\n\n    int ac_circ_buf_push(ac_circ_buf_t *cbuf, void *buf);\n\n#### ac\\_circ\\_buf\\_popm - pop multiple items from buffer\n\n    int ac_circ_buf_popm(ac_circ_buf_t *cbuf, void *buf, u32 count);\n\n#### ac\\_circ\\_buf\\_pop - pop an item from the buffer\n\n    void *ac_circ_buf_pop(ac_circ_buf_t *cbuf);\n\n#### ac\\_circ\\_buf\\_foreach - iterate over elements in the circular buffer\n\n    void ac_circ_buf_foreach(const ac_circ_buf_t *cbuf,\n                             void (*action)(void *item, void *data),\n                             void *user_data);\n\n#### ac\\_circ\\_buf\\_reset - reset the circular buffer to empty\n\n    void ac_circ_buf_reset(ac_circ_buf_t *cbuf);\n\n#### ac\\_circ\\_buf\\_destroy - destroy a circular buffer\n\n    void ac_circ_buf_destroy(const ac_circ_buf_t *cbuf);\n\n\n### Filesystem related functions\n\n#### ac\\_fs\\_is\\_posix\\_name - checks if a filename follows POSIX guidelines\n\n    bool ac_fs_is_posix_name(const char *name);\n\n#### ac\\_fs\\_mkdir\\_p - mkdir with parents\n\n    int ac_fs_mkdir_p(int dirfd, const char *path, mode_t mode);\n\n#### ac\\_fs\\_copy - copy a file\n\n    ssize_t ac_fs_copy(const char *from, const char *to, int flags);\n\n\n### Geospatial related functions\n\n#### ac\\_geo\\_dd\\_to\\_dms - convert decimal degrees into degrees, minutes \u0026 seconds\n\n    void ac_geo_dd_to_dms(double degrees, ac_geo_dms_t *dms);\n\n#### ac\\_geo\\_dms\\_to\\_dd - convert degrees, minutes \u0026 seconds into decimal degrees\n\n    double ac_geo_dms_to_dd(const ac_geo_dms_t *dms);\n\n#### ac\\_geo\\_haversine - calculate the distance between two points on Earth\n\n    double ac_geo_haversine(const ac_geo_t *from, const ac_geo_t *to);\n\n#### ac\\_geo\\_vincenty\\_direct - given an initial point, bearing and distance calculate the end point\n\n    void ac_geo_vincenty_direct(const ac_geo_t *from, ac_geo_t *to,\n                                double distance);\n\n#### ac\\_geo\\_bng\\_to\\_lat\\_lon - convert British National grid Eastings \u0026 Northings to latitude \u0026 longitude decimal degrees\n\n    void ac_geo_bng_to_lat_lon(ac_geo_t *geo);\n\n#### ac\\_geo\\_lat\\_lon\\_to\\_bng - convert latitude \u0026 longitude decimal degrees to British National Grid Eastings \u0026 Northings\n\n    void ac_geo_lat_lon_to_bng(ac_geo_t *geo);\n\n\n### Hash Table functions\n\n#### ac\\_htable\\_new - create a new hash table\n\n    ac_htable_t *ac_htable_new(u32 (*hash_func)(const void *key),\n                               int (*key_cmp)(const void *a, const void *b),\n                               void (*free_key_func)(void *key),\n                               void (*free_data_func)(void *data));\n\n#### ac\\_htable\\_insert - inserts a new entry into a hash table\n\n    void ac_htable_insert(ac_htable_t *htable, void *key, void *data);\n\n#### ac\\_htable\\_remove - remove an entry from a hash table\n\n    bool ac_htable_remove(ac_htable_t *htable, const void *key);\n\n#### ac\\_htable\\_lookup - lookup an entry in a hash table\n\n    void *ac_htable_lookup(const ac_htable_t *htable, const void *key);\n\n#### ac\\_htable\\_foreach - iterate over each entry in a hash table\n\n    void ac_htable_foreach(const ac_htable_t *htable,\n                           void (*action)(void *key, void *value,\n                                          void *user_data), void *user_data);\n\n#### ac\\_htable\\_destroy - destroy the given hash table\n\n    void ac_htable_destroy(const ac_htable_t *htable);\n\n\n### JSON functions\n\n#### ac\\_json\\_load\\_from\\_fd - loads json from an open file descriptor\n\n    char *ac_json_load_from_fd(int fd, off_t offset);\n\n#### ac\\_json\\_load\\_from\\_file - loads json from the specified file\n\n    char *ac_json_load_from_file(const char *file, off_t offset);\n\n\n### JSON Writer functions\n\n#### ac\\_jsonw\\_init - initialises a new ac\\_jsonw\\_t object\n\n    ac_jsonw_t *ac_jsonw_init(void);\n\n#### void ac\\_jsonw\\_indent\\_sz - set the JSON indentation size\n\n    void ac_jsonw_indent_sz(ac_jsonw_t *json, int size);\n\n#### ac\\_jsonw\\_set\\_indenter - set the indentation character/string\n\n    void ac_jsonw_set_indenter(ac_jsonw_t *json, const char *indenter);\n\n#### ac\\_jsonw\\_add\\_str - adds a string to the JSON\n\n    void ac_jsonw_add_str(ac_jsonw_t *json, const char *name,\n                          const char *value);\n\n#### ac\\_jsonw\\_add\\_int - adds an integer to the JSON\n\n    void ac_jsonw_add_int(ac_jsonw_t *json, const char *name, s64 value);\n\n#### ac\\_jsonw\\_add\\_real - adds a realnumber to the JSON\n\n    void ac_jsonw_add_real(ac_jsonw_t *json, const char *name, double value,\n                           int dp);\n\n#### ac\\_jsonw\\_add\\_bool - adds a boolean value to the JSON\n\n    void ac_jsonw_add_bool(ac_jsonw_t *json, const char *name, bool value);\n\n#### ac\\_jsonw\\_add\\_null - adds a null value to the JSON\n\n    void ac_jsonw_add_null(ac_jsonw_t *json, const char *name);\n\n#### ac\\_jsonw\\_add\\_str\\_or\\_null - adds a string or a null value to the JSON\n\n    void ac_jsonw_add_str_or_null(ac_jsonw_t *json, const char *name,\n                                  const char *value);\n\n#### ac\\_jsonw\\_add\\_array - adds an array to the JSON\n\n    void ac_jsonw_add_array(ac_jsonw_t *json, const char *name);\n\n#### ac\\_jsonw\\_end\\_array - ends a JSON array\n\n    void ac_jsonw_end_array(ac_jsonw_t *json);\n\n#### ac\\_jsonw\\_add\\_object - adds a new JSON object to the JSON\n\n    void ac_jsonw_add_object(ac_jsonw_t *json, const char *name);\n\n#### ac\\_jsonw\\_end\\_object - ends a JSON object\n\n    void ac_jsonw_end_object(ac_jsonw_t *json);\n\n#### ac\\_jsonw\\_end - ends the JSON\n\n    void ac_jsonw_end(ac_jsonw_t *json);\n\n#### ac\\_jsonw\\_free - free's the ac\\_jsonw\\_t object\n\n    void ac_jsonw_free(const ac_jsonw_t *json);\n\n#### ac\\_jsonw\\_len - gets the length of the created JSON\n\n    size_t ac_jsonw_len(const ac_jsonw_t *json);\n\n#### ac\\_jsonw\\_get - gets the created JSON\n\n    const char *ac_jsonw_get(const ac_jsonw_t *json);\n\n\n### Miscellaneous functions\n\n#### ac\\_misc\\_ppb - pretty print bytes\n\n    void ac_misc_ppb(u64 bytes, ac_si_units_t si, ac_misc_ppb_t *ppb);\n\n#### ac\\_misc\\_passcrypt\n\n    char *ac_misc_passcrypt(const char *pass, ac_hash_algo_t hash_type,\n                            ac_crypt_data_t *data);\n\n#### ac\\_misc\\_gen\\_uuid4 - generate a type 4 UUID\n\n    const char *ac_misc_gen_uuid4(char *dst);\n\n#### ac\\_misc\\_luhn\\_check - perform the Luhn Check on a number\n\n    bool ac_misc_luhn_check(u64 num);\n\n#### ac\\_misc\\_shuffle - shuffle a list of elements\n\n    int ac_misc_shuffle(void *base, size_t nmemb, size_t size,\n                        ac_misc_shuffle_t algo);\n\n#### ac\\_hash\\_func\\_str - create a hash value for a given string\n\n    u32 ac_hash_func_str(const void *key);\n\n#### ac\\_hash\\_func\\_u32 - create a hash value for a given u32\n\n    u32 ac_hash_func_u32(const void *key);\n\n#### ac\\_hash\\_func\\_ptr - create a hash for a given pointer\n\n    u32 ac_hash_func_ptr(const void *key);\n\n#### ac\\_cmp\\_ptr - compare two pointers\n\n    int ac_cmp_ptr(const void *a, const void *b};\n\n#### ac\\_cmp\\_str - compare two strings\n\n    int ac_cmp_str(const void *a, const void *b);\n\n#### ac\\_cmp\\_u32 - compare two u32's\n\n    int ac_cmp_u32(const void *a, const void *b);\n\n\n### Network related functions\n\n#### ac\\_net\\_port\\_from\\_sa - extract the port number from a struct sockaddr\n\n    int ac_net_port_from_sa(const struct sockaddr *sa);\n\n#### ac\\_net\\_inet\\_pton - address family agnostic wrapper around inet\\_pton(3)\n\n    int ac_net_inet_pton(const char *src, void *dst);\n\n#### ac\\_net\\_inet\\_ntop - address family agnostic wrapper around inet\\_ntop(3)\n\n    const char *ac_net_inet_ntop(const void *src, char *dst, socklen_t size);\n\n#### ac\\_net\\_ns\\_lookup\\_by\\_host - lookup a host by hostname (get its IP(s))\n\n    int ac_net_ns_lookup_by_host(const struct addrinfo *hints,\n                                 const char *node,\n                                 bool (*ac_ns_lookup_cb)\n                                      (const struct addrinfo *ai,\n                                       const char *res));\n\n#### ac\\_net\\_ns\\_lookup\\_by\\_ip - lookup a host by IP address (get its hostname)\n\n    int ac_net_ns_lookup_by_ip(const struct addrinfo *hints,\n                               const char *node,\n                               bool (*ac_ns_lookup_cb)\n                                    (const struct addrinfo *ai,\n                                     const char *res));\n\n#### ac\\_net\\_ipv4\\_isin - check if an IPv4 address is within the given network\n\n    bool ac_net_ipv4_isin(const char *network, u8 cidr, const char *addr);\n\n#### ac\\_net\\_ipv4\\_isin\\_sa - check if an IPv4 address is within the given network\n\n    bool ac_net_ipv4_isin_sa(const char *network, u8 cidr,\n                             const struct sockaddr *sa);\n\n#### ac\\_net\\_ipv6\\_isin - check if an IPv6 address is within the given network\n\n    bool ac_net_ipv6_isin(const char *network, u8 prefixlen, const char *addr);\n\n#### ac\\_net\\_ipv6\\_isin\\_sa - check if an IPv6 address is within the given network\n\n    bool ac_net_ipv6_isin_sa(const char *network, u8 prefixlen,\n                             const struct sockaddr *sa);\n\n\n### Quark functions\n\n#### ac\\_quark\\_init - initialise a new quark\n\n    void ac_quark_init(ac_quark_t *quark, void(*free_func)(void *ptr));\n\n#### ac\\_quark\\_from\\_string - create a new string mapping\n\n    int ac_quark_from_string(ac_quark_t *quark, const char *str);\n\n#### ac\\_quark\\_to\\_string - retrieve the given string\n\n    const char *ac_quark_to_string(const ac_quark_t *quark, int id);\n\n#### ac\\_quark\\_destroy - destroy a quark\n\n    void ac_quark_destroy(const ac_quark_t *quark);\n\n\n### Queue functions\n\n#### ac\\_queue\\_new - create a new queue\n\n    ac_queue_t *ac_queue_new(void);\n\n#### ac\\_queue\\_push - add an item to the queue\n\n    int ac_queue_push(ac_queue_t *queue, void *item);\n\n#### ac\\_queue\\_pop - get the head element from the queue\n\n    void *ac_queue_pop(ac_queue_t *queue);\n\n#### ac\\_queue\\_foreach - iterate over elements in a queue\n\n    void ac_queue_foreach(const ac_queue_t *queue,\n                          void (*action)(void *item, void *data),\n                          void *user_data);\n\n#### ac\\_queue\\_nr\\_items - get the number of elements in the queue\n\n    u32 ac_queue_nr_items(const ac_queue_t *queue);\n\n#### ac\\_queue\\_destroy - destroy a queue freeing all its memory\n\n    void ac_queue_destroy(const ac_queue_t *queue, (*free_func)(void *item));\n\n\n### Doubly linked list functions\n\n#### ac\\_list\\_last - find the last item in the list\n\n    ac_list_t *ac_list_last(ac_list_t *list);\n\n#### ac\\_list\\_len - return the number of entries in the list\n\n    long ac_list_len(const ac_list_t *list);\n\n#### ac\\_list\\_add - add an item to the end of the list\n\n    void ac_list_add(ac_list_t **list, void *data);\n\n#### ac\\_list\\_preadd - add an item to the front of the list\n\n    void ac_list_preadd(ac_list_t **list, void *data);\n\n#### ac\\_list\\_remove - remove an item from the list\n\n    bool ac_list_remove(ac_list_t **list, void *data,\n                        void (*free_data)(void *data));\n\n#### ac\\_list\\_remove\\_nth - remove the nth item from the list\n\n    bool ac_list_remove_nth(ac_list_t **list, long n,\n                            void (*free_data)(void *data));\n\n#### ac\\_list\\_remove\\_custom - remove an item from the list with the given data\n\n    bool ac_list_remove_custom(ac_list_t **list, void *data,\n                               int (*compar)(const void *a, const void *b),\n                               void (*free_data)(void *data));\n\n#### ac\\_list\\_reverse - reverse a list\n\n    void ac_list_reverse(ac_list_t **list);\n\n#### ac\\_list\\_find - find an item in the list\n\n    ac_list_t *ac_list_find(ac_list_t *list, const void *data);\n\n#### ac\\_list\\_find\\_custom - find an item in the list with the given data\n\n    ac_list_t *ac_list_find_custom(ac_list_t *list, const void *data,\n                                   int (*compar)(const void *a,\n                                                 const void *b));\n\n#### ac\\_list\\_nth\\_data - retrieve the item's data at position n\n\n    void *ac_list_nth_data(ac_list_t *list, long n)\n\n#### ac\\_list\\_foreach - execute a function for each item in the list\n\n    void ac_list_foreach(ac_list_t *list,\n                         void (*action)(void *item, void *data),\n                         void *user_data);\n\n#### ac\\_list\\_rev\\_foreach - execute a function for each item in the list in reverse\n\n    void ac_list_rev_foreach(ac_list_t *list,\n                             void (*action)(void *item, void *data),\n                             void *user_data);\n\n#### ac\\_list\\_destroy - destroy a list, optionally freeing all its items memory\n\n    void ac_list_destroy(ac_list_t **list, void (*free_data)(void *data));\n\n\n### Singly linked list functions\n\n#### ac\\_slist\\_last - find the last item in the list\n\n    ac_slist_t *ac_slist_last(ac_slist_t *list);\n\n#### ac\\_slist\\_len - return the number of entries in the list\n\n    long ac_slist_len(const ac_slist_t *list);\n\n#### ac\\_slist\\_add - add an item to the end of the list\n\n    void ac_slist_add(ac_slist_t **list, void *data);\n\n#### ac\\_slist\\_preadd - add an item to the front of the list\n\n    void ac_slist_preadd(ac_slist_t **list, void *data);\n\n#### ac\\_slist\\_remove - remove an item from the list\n\n    bool ac_slist_remove(ac_slist_t **list, void *data, void (*free_data)\n                                                             (void *data));\n\n#### ac\\_slist\\_remove\\_nth - remove the nth item from the list\n\n    bool ac_slist_remove_nth(ac_slist_t **list, long n, void (*free_data)\n                                                             (void *data));\n\n#### ac\\_slist\\_remove\\_custom - remove an item from the list with the given data\n\n    bool ac_slist_remove_custom(ac_slist_t **list, void *data,\n                                int (*compar)(const void *a, const void *b),\n                                void (*free_data)(void *data));\n\n#### ac\\_slist\\_reverse - reverse a list\n\n    void ac_slist_reverse(ac_slist_t **list);\n\n#### ac\\_slist\\_find - find an item in the list\n\n    ac_slist_t *ac_slist_find(ac_slist_t *list, const void *data);\n\n#### ac\\_slist\\_find\\_custom - find an item in the list with the given data\n\n    ac_slist_t *ac_slist_find_custom(ac_slist_t *list, const void *data,\n                                     int (*compar)(const void *a,\n                                                   const void *b));\n\n#### ac\\_slist\\_nth\\_data - retrieve the item's data at position n\n\n    void *ac_slist_nth_data(ac_slist_t *list, long n);\n\n#### ac\\_slist\\_foreach - execute a function for each item in the list\n\n    void ac_slist_foreach(ac_slist_t *list,\n                          void (*action)(void *item, void *data),\n                          void *user_data);\n\n#### ac\\_slist\\_destroy - destroy a list, optionally freeing all its items memory\n\n    void ac_slist_destroy(ac_slist_t **list, void (*free_data)(void *data));\n\n\n### String functions\n\n#### ac\\_str\\_freev - free a string vector\n\n    void ac_str_freev(char **stringv);\n\n#### ac\\_str\\_split - split a string up into a NULL terminated vector\n\n    char **ac_str_split(const char *string, int delim, int flags);\n\n#### ac\\_str\\_chomp - remove trailing white space from a string\n\n    char *ac_str_chomp(char *string);\n\n#### ac\\_str\\_substr - extract a substring from a string\n\n    char *ac_str_substr(const char *src, char *dest, size_t start, size_t len);\n\n#### ac\\_str\\_levenshtein - calculate the Levenshtein distance between two strings\n\n    int ac_str_levenshtein(const char *s, const char *t);\n\n\n### Time related functions\n\n#### ac\\_time\\_tspec\\_diff - subtract two struct timespec's\n\n    double ac_time_tspec_diff(struct timespec *delta,\n                              const struct timespec *end,\n                              const struct timespec *start);\n\n#### ac\\_time\\_secs\\_to\\_hms - convert total seconds to broken out hrs, mins \u0026 secs\n\n    void ac_time_secs_to_hms(long total, int *hours, int *minutes,\n                             int *seconds);\n\n#### ac\\_time\\_nsleep - wrapper around nanosleep(2) that sleeps through interrupts\n\n    int ac_time_nsleep(u64 nsecs);\n\n\n## Build it\n\nlibac is primarily developed under Linux but it also builds and runs under\nFreeBSD.\n\n### Linux\n\nThe simplest way is to build the rpm by simply doing\n\n    $ make rpm\n\nin the repository root. It just needs a suitable *rpmbuild/* directory\nstructure which can be created with\n\n    $ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}\n\nand the *rpmbuild* tool which can be found in the *rpm-build* package.\n\n### FreeBSD\n\nlibac has a single dependency on FreeBSD of libuuid, it also needs to be built\nwith gmake (GNU make), these can be installed with\n\n    $ sudo pkg install e2fsprogs-libuuid gmake\n\nthen libac can be built with\n\n    $ gmake\n\nor if you don't have GCC installed\n\n    $ gmake CC=clang\n\n## How to use\n\nJust\n\n    #include \u003clibac.h\u003e\n\nin your program and link with *-lac* assuming you've built and installed the\nRPM or similar.\n\nSee *src/test.c* for examples on using the above.\n\n\n## Thread safety\n\nlibac is intended to be thread-safe.\n\n\n## License\n\nThis library is licensed under the GNU Lesser General Public License (LGPL)\nversion 2.1\n\nSee *COPYING* in the repository root for details.\n\n\n## Contributing\n\nSee *CodingStyle.md* \u0026 *Contributing.md*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fac000%2Flibac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fac000%2Flibac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fac000%2Flibac/lists"}