hashlist

type-safe random access double linked lists
git clone https://noulin.net/git/hashlist.git
Log | Files | Refs | README | LICENSE

commit 6d17a10b62bfafca0454b13f03e91f9516b2c73f
parent 65276d075e2f1f533c3819b40b139cedd1129ca1
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sun, 23 Dec 2018 12:34:44 +0100

random access double linked list

README.md   |  24 ++++
hashlist.h  | 407 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
main.c      | 108 ++++++++++++++++
package.yml |  31 +++++
4 files changed, 570 insertions(+)

Diffstat:
AREADME.md | 24++++++++++++++++++++++++
Ahashlist.h | 407+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amain.c | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.yml | 31+++++++++++++++++++++++++++++++
4 files changed, 570 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,24 @@ +# Sheepy +This is a sheepy package for [sheepy](https://github.com/RemyNoulin/sheepy) and using [libsheepy](https://github.com/RemyNoulin/libsheepy) + +# Random access double linked lists + +Hashlist holds double linked lists in a hashtable, each node in the list has a key, any node in the list is accessed using a key. +Node are accessed in O(1) as in hashtables. + +The data can be stored in the list nodes to reduce the frequency of memory allocations. + + +# Usage + +Install with spm: `spm install hashlist` + +Include header file: +- `#include "shpPackages/hashlist/hashlist.h"` + +Usage examples are on the top of the headers and in `main.c`. + +Before running `main.c` install the hashfunctions with: +``` +spm install hashfunctions +``` diff --git a/hashlist.h b/hashlist.h @@ -0,0 +1,407 @@ +#pragma once + +#include "libsheepyObject.h" +#include "shpPackages/hashtable/hashtable.h" + +/** + * \file + * + * hashlist - random access double linked lists + * + * this data structure is a double linked list in a hashtable + * each node in the list has a key, any node in the list is accessed using a key + * multiple lists can be created in the hashtable + * + * the macros in this define and implement the hashlist types and functions + * the hash function has to be provided by another package (hashfunctions) + * + * - hashlistDef defines the types and function prototype for the hashlist and hashtable + * - hashlistFunctions implements the hashlist and hashtable functions + * + * the hashlist function names have the following pattern: + * hashlistFUNCTION_NAME##hashlistFuncSuffix + * + * the hashtable function names have the following pattern: + * FUNCTION_NAME##hashlistFuncSuffix + * + * the hashlist type is: hashlistTypeName##t + * the hashlist node type is: valueTypeName##t + * + * node.key is the key + * node.prev is a pointer to previous node, NULL when node is head + * node.next is a pointer to next node, NULL when node is last + * + * Use the regular hashtable functions to access the nodes using the keys: get####hashlistFuncSuffix, find##hashlistFuncSuffix... + * + * Push, Prepend, AppendAfter, AppendBefore add new nodes and return a pointer to it + * AddAfter, AddAfterKey, AddBefore, AddBeforeKey add new nodes and store the value in parameter in it + * + * Use Unlink to crop a node from the list and then use the FreeNode or Insert functions + * + * function descriptions: + * + * - Create: create a new list and store value in first node. + * Returns: node pointer or NULL when key already exists + * - New: create a new list and a new node with given key. + * Returns: node pointer or NULL when key already exists + * - Free: free all nodes in list (nodes before and after given node are freed, node doesn't need to be head or last) + * - Release: free all nodes in list starting with node with given key + * (nodes before and after given key are freed, node doesn't need to be head or last) + * - Push: add a new node with newKey after given node. + * Returns: new node pointer or NULL when node is NULL or when key already exists + * - Prepend: add a new node with newKey before given node. + * Returns: new node pointer or NULL when node is NULL or when key already exists + * - AppendAfter: add a new node with newKey after node given key. + * Returns: new node pointer or NULL when key doesn't exists or when key already exists + * - AppendBefore: add a new node with newKey before node given key. + * Returns: new node pointer or NULL when key doesn't exists or when key already exists + * - Unlink: crop node from the list. + * Returns node pointer or NULL when node is NULL + * - UnlinkKey: crop node with given key from the list. + * Returns node pointer or NULL when key doesn't exists + * - FreeNode (del##hashlistFuncSuffix): free an unlinked node. + * Returns: true or false when node is NULL + * - DelNode: unlink and free node + * - Del: unlink and free node with given key + * - InsertAfter: insert unlinked node after given node. Returns node pointer or NULL when node or value are NULL + * - InsertAfterKey: insert unlinked node after node with key. Returns node pointer or NULL when key doesn't exists or value is NULL + * - InsertBefore: insert unlinked node before given node. Returns node pointer or NULL when node or value are NULL + * - InsertBeforeKey: insert unlinked node before node with key. Returns node pointer or NULL when key doesn't exists or value is NULL + * - AddAfter: add new node and store value in it after node. + * Returns: new node pointer or NULL when node is NULL or value.key already exists + * - AddAfterKey: add new node and store value in it after node with given key. + * Returns: new node pointer or NULL when key doesn't exists or value.key already exists + * - AddBefore: add new node and store value in it before node. + * Returns: new node pointer or NULL when node is NULL or value.key already exists + * - AddBeforeKey: add new node and store value in it before node with given key. + * Returns: new node pointer or NULL when key doesn't exists or value.key already exists + * + * Example: + * See main.c for more details + * + * // define node members: + * #define listMembers char *v; + * + * // define hashlist + * hashlistDef(, lists, Lists, u64, list, u64, listMembers); + * + * // select hashtable functions + * #define HASHFUNC u64Hash + * #define CMPFUNC cmpU64 + * #define FREEFUNC freeList + * + * // implement hashlist functions + * hashlistFunctions(, lists, Lists, u64, list, u64, listMembers, + * int cmpU64(u64 k1, u64 k2) { + * return k1 == k2; + * } + * void freeList(u64 *k, listt *v) { + * }); + * + * // undef functions + * #undef HASHFUNC + * #undef CMPFUNC + * #undef FREEFUNC + * + * // declare hashlist + * listst hlists; + * + * // initlialize hashlist + * initLists(&hlists); + * + * // declare hashlist node + * listt g; + * + * // create new list + * g.key = 0; + * g.v = "sdf"; + * listt *head = hashlistCreateLists(&hlists, g); + * + * // access node + * listt *G = findLists(&hlists, 0); + * logVarG(G->v); + * + * // push new node + * G = hashlistPushLists(&hlists, head, 1); + * G->v = "22"; + * + * // free list + * hashlistFreeLists(&hlists, head); + * + * // free hashlist + * freeLists(&hlists); + * + */ + +#define hashlistDef(scope, hashlistTypeName, hashlistFuncSuffix, keyType, valueTypeName, hashType, valueMembers)\ + typ struct valueTypeName##t valueTypeName##t;\ + struct valueTypeName##t {\ + /* linked list */\ + keyType key;\ + valueTypeName##t *prev; /* prev list node */\ + valueTypeName##t *next; /* next list node */\ + valueMembers\ + };\ + \ + hashTbDef(scope, hashlistTypeName /* hashlistTypeNamet hashtable */, hashlistFuncSuffix /* functions: inithashlistFuncSuffix,... */, keyType /* key */, valueTypeName##t /* value */, hashType /* hash */);\ + scope valueTypeName##t* hashlistCreate##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t value);\ + scope valueTypeName##t* hashlistNew##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key);\ + scope void hashlistFree##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node);\ + scope void hashlistRelease##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key);\ + scope valueTypeName##t* hashlistPush##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, keyType newKey);\ + scope valueTypeName##t* hashlistPrepend##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, keyType newKey);\ + scope valueTypeName##t* hashlistAppendAfter##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, keyType newKey);\ + scope valueTypeName##t* hashlistAppendBefore##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, keyType newKey);\ + scope valueTypeName##t* hashlistUnlink##hashlistFuncSuffix(valueTypeName##t *node);\ + scope valueTypeName##t* hashlistUnlinkKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key);\ + scope bool hashlistFreeNode##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node);\ + scope bool hashlistDelNode##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node);\ + scope void hashlistDel##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key);\ + scope valueTypeName##t* hashlistInsertAfter##hashlistFuncSuffix(valueTypeName##t *node, valueTypeName##t *value);\ + scope valueTypeName##t* hashlistInsertAfterKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t *value);\ + scope valueTypeName##t* hashlistInsertBefore##hashlistFuncSuffix(valueTypeName##t *node, valueTypeName##t *value);\ + scope valueTypeName##t* hashlistInsertBeforeKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t *value);\ + scope valueTypeName##t* hashlistAddAfter##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, valueTypeName##t value);\ + scope valueTypeName##t* hashlistAddAfterKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t value);\ + scope valueTypeName##t* hashlistAddBefore##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, valueTypeName##t value);\ + scope valueTypeName##t* hashlistAddBeforeKey(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t value); + +#define hashlistFunctions(scope, hashlistTypeName, hashlistFuncSuffix, keyType, valueTypeName, hashType, valueMembers, functions /* declare the functions here */)\ + functions;\ + \ + hashTbFunctions(scope, hashlistTypeName, hashlistFuncSuffix, keyType /* key */, valueTypeName##t /* value */)\ + /* create head - first node in list */\ + scope valueTypeName##t* hashlistCreate##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t value) {\ + value.prev = value.next = NULL;\ + bool r;\ + valueTypeName##t* res = addOrFind##hashlistFuncSuffix(hashlist, value.key, &r);\ + if (!r) ret NULL;\ + *res = value;\ + ret res;\ + }\ + /* create new head with given key - first node in list */\ + scope valueTypeName##t* hashlistNew##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key) {\ + bool r;\ + valueTypeName##t* res = addOrFind##hashlistFuncSuffix(hashlist, key, &r);\ + if (!r) ret NULL;\ + res->prev = res->next = NULL;\ + res->key = key;\ + ret res;\ + }\ + /* free list */\ + scope void hashlistFree##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node) {\ + if (!node) ret;\ + if (node->next) {\ + if (node->prev) {\ + /* there are nodes before and after */\ + var prev = node->prev;\ + /* delete node and next nodes */\ + var n = node;\ + var tmp = n;\ + while (n) {\ + tmp = n->next;\ + del##hashlistFuncSuffix(hashlist, n->key);\ + n = tmp;\ + }\ + /* delete previous nodes */\ + n = prev;\ + while (n) {\ + tmp = n->prev;\ + del##hashlistFuncSuffix(hashlist, n->key);\ + n = tmp;\ + }\ + }\ + else {\ + /* node is head, there are only next nodes*/\ + var n = node;\ + var tmp = n;\ + while (n) {\ + tmp = n->next;\ + del##hashlistFuncSuffix(hashlist, n->key);\ + n = tmp;\ + }\ + }\ + }\ + else {\ + /* node is last, there are only previous nodes */\ + var n = node;\ + var tmp = n;\ + while (n) {\ + tmp = n->prev;\ + del##hashlistFuncSuffix(hashlist, n->key);\ + n = tmp;\ + }\ + }\ + }\ + /* free list using key */\ + scope void hashlistRelease##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + hashlistFree##hashlistFuncSuffix(hashlist, node);\ + }\ + /* push */\ + scope valueTypeName##t* hashlistPush##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, keyType newKey) {\ + if (!node) ret NULL;\ + bool r;\ + valueTypeName##t *val = addOrFind##hashlistFuncSuffix(hashlist, newKey, &r);\ + if (!r) /* key already exists, failed to create new node */ ret NULL;\ + val->key = newKey;\ + /* connect new node to list */\ + val->next = node->next;\ + if (val->next) {\ + val->next->prev = val;\ + }\ + node->next = val;\ + val->prev = node;\ + ret val;\ + }\ + /* prepend */\ + scope valueTypeName##t* hashlistPrepend##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, keyType newKey) {\ + if (!node) ret NULL;\ + bool r;\ + valueTypeName##t *val = addOrFind##hashlistFuncSuffix(hashlist, newKey, &r);\ + if (!r) /* key already exists, failed to create new node */ ret NULL;\ + val->key = newKey;\ + /* connect new node to list */\ + val->prev = node->prev;\ + if (val->prev) {\ + val->prev->next = val;\ + }\ + node->prev = val;\ + val->next = node;\ + ret val;\ + }\ + /* append new node after node with key */\ + scope valueTypeName##t* hashlistAppendAfter##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, keyType newKey) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistPush##hashlistFuncSuffix(hashlist, node, newKey);\ + }\ + /* append new node before node with key */\ + scope valueTypeName##t* hashlistAppendBefore##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, keyType newKey) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistPrepend##hashlistFuncSuffix(hashlist, node, newKey);\ + }\ + /* unlink */\ + scope valueTypeName##t* hashlistUnlink##hashlistFuncSuffix(valueTypeName##t *node) {\ + if (!node) ret NULL;\ + if (node->prev) {\ + node->prev->next = node->next;\ + }\ + if (node->next) {\ + node->next->prev = node->prev;\ + }\ + return node;\ + }\ + /* unlink with key */\ + scope valueTypeName##t* hashlistUnlinkKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistUnlink##hashlistFuncSuffix(node);\ + }\ + /* free unlinked node */\ + scope bool hashlistFreeNode##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node) {\ + if (!node) ret false;\ + del##hashlistFuncSuffix(hashlist, node->key);\ + ret true;\ + }\ + /* del node */\ + scope bool hashlistDelNode##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node) {\ + if (!node) ret false;\ + hashlistUnlink##hashlistFuncSuffix(node);\ + del##hashlistFuncSuffix(hashlist, node->key);\ + ret true;\ + }\ + /* del using key */\ + scope void hashlistDel##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key) {\ + hashlistTypeName##Nodet *node = unlink##hashlistFuncSuffix(hashlist, key);\ + if (!node) /* node not found */ ret;\ + hashlistUnlink##hashlistFuncSuffix(&node->value);\ + freeUnlinked##hashlistFuncSuffix(hashlist, node);\ + }\ + /* TODO swap 2 nodes */\ + /* insert an unlinked value after node */\ + scope valueTypeName##t* hashlistInsertAfter##hashlistFuncSuffix(valueTypeName##t *node, valueTypeName##t *value) {\ + if (!node or !value) ret NULL;\ + /* connect value node to list */\ + value->next = node->next;\ + if (value->next) {\ + value->next->prev = value;\ + }\ + node->next = value;\ + value->prev = node;\ + ret value;\ + }\ + /* insert an unlinked value after node with key */\ + scope valueTypeName##t* hashlistInsertAfterKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t *value) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistInsertAfter##hashlistFuncSuffix(node, value);\ + }\ + /* insert an unlinked value before node */\ + scope valueTypeName##t* hashlistInsertBefore##hashlistFuncSuffix(valueTypeName##t *node, valueTypeName##t *value) {\ + if (!node or !value) ret NULL;\ + /* connect value node to list */\ + value->prev = node->prev;\ + if (value->prev) {\ + value->prev->next = value;\ + }\ + node->prev = value;\ + value->next = node;\ + ret value;\ + }\ + /* insert an unlinked value before node with key */\ + scope valueTypeName##t* hashlistInsertBeforeKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t *value) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistInsertBefore##hashlistFuncSuffix(node, value);\ + }\ + /* Add new node after node */\ + scope valueTypeName##t* hashlistAddAfter##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, valueTypeName##t value) {\ + if (!node) ret NULL;\ + bool r;\ + valueTypeName##t *val = addOrFind##hashlistFuncSuffix(hashlist, value.key, &r);\ + if (!r) /* key already exists, failed to create new node */ ret NULL;\ + /* copy data to new node */\ + *val = value;\ + /* connect new node to list */\ + val->next = node->next;\ + if (val->next) {\ + val->next->prev = val;\ + }\ + node->next = val;\ + val->prev = node;\ + ret val;\ + }\ + /* Add new node after node for given key */\ + scope valueTypeName##t* hashlistAddAfterKey##hashlistFuncSuffix(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t value) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistAddAfter##hashlistFuncSuffix(hashlist, node, value);\ + }\ + /* Add new node before node */\ + scope valueTypeName##t* hashlistAddBefore##hashlistFuncSuffix(hashlistTypeName##t *hashlist, valueTypeName##t *node, valueTypeName##t value) {\ + if (!node) ret NULL;\ + bool r;\ + valueTypeName##t *val = addOrFind##hashlistFuncSuffix(hashlist, value.key, &r);\ + if (!r) /* key already exists, failed to create new node */ ret NULL;\ + /* copy data to new node */\ + *val = value;\ + /* connect new node to list */\ + val->prev = node->prev;\ + if (val->prev) {\ + val->prev->next = val;\ + }\ + node->prev = val;\ + val->next = node;\ + ret val;\ + }\ + /* Add new node before node for given key */\ + scope valueTypeName##t* hashlistAddBeforeKey(hashlistTypeName##t *hashlist, keyType key, valueTypeName##t value) {\ + valueTypeName##t *node = find##hashlistFuncSuffix(hashlist, key);\ + ret hashlistAddBefore##hashlistFuncSuffix(hashlist, node, value);\ + }\ + /* write/read */ + + +// forEach: lForEach(node, startNode) regular linked list forEach from libsheepy.h +#define hashlistForEach lForEach +#define hashlistForEachDown lForEachDown +#define hashlistForEachPrev lForEachPrev + + +// vim: set expandtab ts=2 sw=2: diff --git a/main.c b/main.c @@ -0,0 +1,108 @@ +#! /usr/bin/env sheepy +#include "libsheepyObject.h" +#include "hashlist.h" +#include "shpPackages/hashfunctions/hashfunctions.h" + +/* hashlist definition and prototypes */ +#define listMembers char *v; + +hashlistDef(/* scope */, lists /* listst hashtable */, Lists /* functions: initLists... */, u64 /* key */, list /* listt value type */, u64 /* hash */, listMembers); + +#define HASHFUNC u64Hash // hash function from the hashfunctions spm package +#define CMPFUNC cmpU64 +#define FREEFUNC freeList + +hashlistFunctions(/* scope */, lists /* listst hashtable */, Lists /* functions: initLists... */, u64 /* key */, list /* listt value type */, u64 /* hash */, listMembers, +int cmpU64(u64 k1, u64 k2) { + return k1 == k2; +} +void freeList(u64 *k, listt *v) { +} + ); + +#undef HASHFUNC +#undef CMPFUNC +#undef FREEFUNC + +int main(int ARGC, char** ARGV) { + + initLibsheepy(ARGV[0]); + setLogMode(LOG_FUNC); + + listst hlists; + + initLists(&hlists); + + listt g; + + g.key = 0; + g.v = "sdf"; + + + listt *head = hashlistCreateLists(&hlists, g); + //listt *head = hashlistNewLists(&hlists, 0); + head->v = "sdf"; + + logVarG(getLists(&hlists, 0).v); + + listt *G = findLists(&hlists, 0); + + logVarG(G->v); + + g.key = 1; + g.v = "22"; + + G = hashlistAddAfterLists(&hlists, G, g); + + G = hashlistPushLists(&hlists, G, 2); + G->v = "333"; + + G = hashlistPushLists(&hlists, G, 3); + G->v = "4444"; + + g.key = 30; + g.v = "3!!!!4"; + + hashlistAddBeforeLists(&hlists, G, g); + + G = hashlistPrependLists(&hlists, G, 31); + G->v = "----4"; + + lForEach(node, head) { + logVarG(node->v); + } + + // unlink key 1 and insert after key 3 + listt *N = hashlistUnlinkLists(head->next); + hashlistInsertAfterLists(G, N); + + put + lForEach(node, head) { + logVarG(node->v); + } + + // delete key 1 + hashlistDelLists(&hlists, 1); + + put + lForEach(node, head) { + logVarG(node->v); + } + + hashlistDelLists(&hlists, 3); + + put + lForEach(node, head) { + logVarG(node->v); + } + + //hashlistFreeLists(&hlists, head); + hashlistReleaseLists(&hlists, 0); + + put + if (findLists(&hlists, 0)) {logI("found head!");} + else logI(BLD GRN"not found head!"RST); + + freeLists(&hlists); +} +// vim: set expandtab ts=2 sw=2: diff --git a/package.yml b/package.yml @@ -0,0 +1,31 @@ +--- + name: hashlist + version: 0.0.1 + description: "random access double linked lists" + bin: ./hashlist.h + #cflags: -DA -ggdb -std=gnu11 -fPIC -pipe + #lflags: -lpcre + repository: + type: git + url: git+https://github.com/RemyNoulin/hashlist.git + keywords: + - data structure + author: Remy Noulin + license: MIT + bugs: + url: https://github.com/RemyNoulin/hashlist/issues + homepage: https://github.com/RemyNoulin/hashlist#readme + compileHelp: main.c depends on the hashfunctions package, install with spm install hashfunctions # text displayed when there is a compilation error + dependencies: + hashtable: + # Test configuration: + #testBin: ./testHashlist.c + #testCflags: -ggdb -std=gnu11 -fPIC -pipe -fprofile-arcs -ftest-coverage -Wall -Wextra + #testLflags: -lcheck_pic -lrt -lm -lsubunit -fprofile-arcs -ftest-coverage -rdynamic + # Memcheck configuration: + #memcheckBin: ./memcheckHashlist.c + #memcheckCmd: valgrind --leak-check=full --show-leak-kinds=all + #memcheckCflags: -ggdb -std=gnu11 -fPIC -pipe + #memcheckLflags: -rdynamic + #documentationCmd: # command for generating the documentation with spm doc + private: false # true for private package