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:
| A | README.md | | | 24 | ++++++++++++++++++++++++ |
| A | hashlist.h | | | 407 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | main.c | | | 108 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | package.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