singleList

Log

Files

Refs

README

LICENSE

isingleList.h (20043B)

     1 
     2 
     3 /**
     4  * \file
     5  *
     6  * Indexed Single linked list: isingleList
     7  *
     8  * head 1 <- 2 <- 3 last
     9  *
    10  * The single linked list can be used as a stack and is not efficient when used as a queue.
    11  *
    12  * The nodes in isingleList are linked with indexes in the internal dArray, in some cases it saves memory compare to using 64 bit pointers. (isingleList is not compatible with lForEach from libsheepy.h)
    13  *
    14  * NOTE: The macros in this file are for creating list functions wrapping the macros.
    15  *
    16  * The number of nodes is defined at list declaration with the index type definition in isingleListT, the nodes are dynamically allocated in segments.
    17  *
    18  * The element type handled by the list is defined with isingleListT
    19  *
    20  * The nodes have 2 members: .elem and .prev, .elem is the element data and .prev is the index of the previous node
    21  *
    22  * use push and pop to stack nodes
    23  *
    24  * The forEach macros loop on nodes or elements from last node to head node
    25  *
    26  * use unlinkPrev or unlinkBefore and unlinkLast to unlink nodes anywhere in the list
    27  *
    28  * use insertBefore, addBefore to insert anywhere in the list, before head and push, insertLast, addLast to insert after last
    29  *
    30  * use freeUnlinked to free unlinked nodes
    31  *
    32  * use isingleListDelPrev or isingleListDelBefore, isingleListDelLast or isingleListPop to delete nodes anywhere in the list
    33  *
    34  * To create a list in reverse order, add the first node with push and then add the nodes with addBefore head
    35  *
    36  * Example:
    37  *
    38  * // define list:
    39  * isingleListT(slt, u32, u32);
    40  *
    41  * // declare list:
    42  * slt sl;
    43  *
    44  * // initialize:
    45  * isingleListInit(&sl, -1);
    46  *
    47  * // push element:
    48  * isingleListPush(&sl);
    49  * isingleListLast(&sl) = 1;
    50  *
    51  * isingleListPush(&sl);
    52  * isingleListLast(&sl) = 2;
    53  *
    54  * // head element
    55  * isingleListHead(&sl) = 0;
    56  *
    57  * // previous node for last node
    58  * u32 prev  = isingleListNodePrev(isingleListLastNode(&sl));
    59  * u32 prev2 = isingleListLastNode(&sl).prev;
    60  * u32 prev3 = isingleListLastPrevIdx(&sl);
    61  * u32 prev4 = isingleListPrevIdx(&sl, isingleListLastIdx(&sl));
    62  * isingleListNode  (&sl, prev).elem    = 4;
    63  * isingleListPrevAt(&sl, sl.last).elem = 4;
    64  *
    65  * // pointer to node
    66  * isingleListNodeType(&sl) pointer = isingleListPtr(&sl, sl.head);
    67  *
    68  * // Pop/delLast element:
    69  * isingleListPop(&sl);
    70  *
    71  * // free list
    72  * isingleListFree(&sl);
    73  */
    74 
    75 #include "libsheepyObject.h"
    76 
    77 /**
    78  * list and node definition
    79  *
    80  * indexType is the type for storing the single node indexes (size_t, u32, ...)
    81  */
    82 #define isingleListT(typeName, indexType, elementType)\
    83   /* node type */\
    84   typ struct UNIQVAR(nodet) UNIQVAR(nodet);\
    85   struct UNIQVAR(nodet) {\
    86     elementType elem;\
    87     indexType prev;\
    88   };\
    89   /* dArray storing the nodes */\
    90   dArrayT(UNIQVAR(aNodet), UNIQVAR(nodet));\
    91   /* free node list */\
    92   dArrayT(UNIQVAR(freeaNodet), indexType);\
    93   typ struct {\
    94     indexType           head; /* first node */\
    95     indexType           last; /* last node */\
    96     indexType           null; /* null value for index */\
    97     UNIQVAR(aNodet)     list; /* node dArray */\
    98     UNIQVAR(freeaNodet) freeList; /* free node dArray */\
    99     size_t              count; /* node count */\
   100   } typeName
   101 
   102 /**
   103  * initialize list
   104  *
   105  * \param
   106  *   nullValue -1 or NULL value for indexType
   107  * \return
   108  *   true success, false failed
   109  */
   110 #define isingleListInit(name, nullValue) ({\
   111   (name)->head = nullValue;\
   112   (name)->last = nullValue;\
   113   (name)->null = nullValue;\
   114   dArrayInit(&(name)->list);\
   115   dArrayInit(&(name)->freeList);\
   116   (name)->count = 0;\
   117   true;\
   118   })
   119 
   120 /**
   121  * free list
   122  * free and reset internal structures
   123  */
   124 #define isingleListFree(name) do{\
   125   dArrayFree(&(name)->list);\
   126   dArrayFree(&(name)->freeList);\
   127   (name)->head = (name)->null;\
   128   (name)->last = (name)->null;\
   129   (name)->count = 0;\
   130   } while(0)
   131 
   132 /**
   133  * node type for declaring pointers to nodes
   134  * */
   135 #define isingleListNodeType(name) dArrayElemPtrType(&(name)->list)
   136 
   137 /**
   138  * is list empty
   139  */
   140 #define isingleListIsEmpty(name) (!(name)->count)
   141 
   142 /**
   143  * element count in list
   144  */
   145 #define isingleListCount(name) (name)->count
   146 
   147 /**
   148  * push element to list (only allocates node)
   149  * use isingleListLast to access the element
   150  *
   151  * \return
   152  *  true success, false failed
   153  */
   154 #define isingleListPush(name) ({\
   155   /* steps:
   156    * check if free node is empty
   157    *  free list is empty, add a new node
   158    *  create first node
   159    *  or link to previous node
   160    * reuse a free node
   161    *  create first node
   162    *  or link to previous node
   163    */\
   164   if (dArrayIsEmpty(&(name)->freeList)) {\
   165     /* free list is empty, add a new node */\
   166     dArrayPush(&(name)->list);\
   167     if (isingleListIsEmpty(name)) {\
   168       /* first node */\
   169       dArrayLast(&(name)->list).prev = (name)->null;\
   170       (name)->head = (name)->last    = dArrayLastIndex(&(name)->list);\
   171     }\
   172     else {\
   173       /* link to previous node */\
   174       dArrayLast(&(name)->list).prev = (name)->last;\
   175       (name)->last                   = dArrayLastIndex(&(name)->list);\
   176     }\
   177   }\
   178   else {\
   179     /* reuse a free node */\
   180     if (isingleListIsEmpty(name)) {\
   181       /* first node */\
   182       dArrayAt(&(name)->list, dArrayLast(&(name)->freeList)).prev = (name)->null;\
   183       (name)->head = (name)->last = dArrayLast(&(name)->freeList);\
   184     }\
   185     else {\
   186       /* link to previous node */\
   187       dArrayAt(&(name)->list, dArrayLast(&(name)->freeList)).prev = (name)->last;\
   188       (name)->last = dArrayLast(&(name)->freeList);\
   189     }\
   190     dArrayDelLast(&(name)->freeList);\
   191   }\
   192   (name)->count++;\
   193   true;\
   194   })
   195 
   196 /**
   197  * pop element from list (only free node)
   198  *
   199  * \return
   200  *   true success, false failed: the list is empty
   201  */
   202 #define isingleListPop(name) ({\
   203   bool UNIQVAR(res) = true;\
   204   if (isingleListIsEmpty(name)) {\
   205     /* the list is empty */\
   206     UNIQVAR(res) = false;\
   207     goto UNIQVAR(ret);\
   208   }\
   209   /* free last node */\
   210   dArrayAppend(&(name)->freeList, (name)->last);\
   211   /* previous node becomes last node */\
   212   (name)->last = dArrayAt(&(name)->list, (name)->last).prev;\
   213   if ((name)->count == 1) /* the list is empty, head is gone */ (name)->head = (name)->null;\
   214   (name)->count--;\
   215   UNIQVAR(ret):\
   216   UNIQVAR(res);\
   217   })
   218 
   219 #define isingleListDelLast isingleListPop
   220 
   221 /**
   222  * unlink previous node (use pop or unlinkLast to unlink the last node)
   223  *
   224  * nodeIndex must be of type indexType
   225  *
   226  * the node can be freed with isingleListFreeUnlinked or
   227  * inserted in the list with isingleListInsertBefore or isingleListInsertLast
   228  *
   229  * \return
   230  *   unlinked node index
   231  *   null index when the list is empty or when nodeIndex is head
   232  */
   233 #define isingleListUnlinkPrev(name, nodeIndex) ({\
   234   typeof((name)->null) UNIQVAR(nodeIdx) = nodeIndex;\
   235   var                  UNIQVAR(res)     = (name)->null;\
   236   if (isingleListIsEmpty(name)) /* list is empty*/ goto UNIQVAR(ret);\
   237   if (UNIQVAR(nodeIdx) == (name)->head) {\
   238     /* node is head, there is no previous node */\
   239     goto UNIQVAR(ret);\
   240   }\
   241   /* the unlinked node is prev */\
   242   UNIQVAR(res) = dArrayAt(&(name)->list, UNIQVAR(nodeIdx)).prev;\
   243   if (UNIQVAR(res) == (name)->head) {\
   244     /* prev node is head, so nodeIndex is now head and update head */\
   245     (name)->head = UNIQVAR(nodeIdx);\
   246     dArrayAt(&(name)->list, UNIQVAR(nodeIdx)).prev = (name)->null;\
   247   }\
   248   else {\
   249     /* link previous previous node to node at nodeIndex */\
   250     dArrayAt(&(name)->list, UNIQVAR(nodeIdx)).prev = dArrayAt(&(name)->list, UNIQVAR(res)).prev;\
   251   }\
   252   (name)->count--;\
   253   UNIQVAR(ret):\
   254   UNIQVAR(res);\
   255   })
   256 
   257 #define isingleListUnlinkBefore isingleListUnlinkPrev
   258 
   259 /**
   260  * unlink last node
   261  *
   262  * the node can be freed with isingleListFreeUnlinked or
   263  * inserted in the list with isingleListInsertBefore or isingleListInsertLast
   264  *
   265  * \return
   266  *   unlinked node index
   267  *   null index when the list is empty
   268  */
   269 #define isingleListUnlinkLast(name) ({\
   270   var UNIQVAR(res) = (name)->null;\
   271   if (isingleListIsEmpty(name)) /* list is empty*/ goto UNIQVAR(ret);\
   272   /* last is unlinked */\
   273   UNIQVAR(res) = (name)->last;\
   274   /* previous node is now last */\
   275   (name)->last = isingleListLastPrevIdx(name);\
   276   (name)->count--;\
   277   /* if the list is empty set head to null */\
   278   if (isingleListIsEmpty(name)) (name)->head = (name)->null;\
   279   UNIQVAR(ret):\
   280   UNIQVAR(res);\
   281   })
   282 
   283 /**
   284  * free unlinked node
   285  *
   286  * nodeIndex must be of type indexType
   287  */
   288 #define isingleListFreeUnlinked(name, nodeIndex) dArrayAppend(&(name)->freeList, nodeIndex)
   289 
   290 /**
   291  * delete node
   292  *
   293  * nodeIndex must be of type indexType
   294  *
   295  * unlink and free node
   296  */
   297 #define isingleListDelPrev(name, nodeIndex) ({\
   298   var UNIQVAR(prev) = isingleListUnlinkPrev(name, nodeIndex);\
   299   isingleListFreeUnlinked(name, UNIQVAR(prev));\
   300   true;\
   301   })
   302 
   303 #define isingleListDelBefore isingleListDelPrev
   304 
   305 
   306 
   307 
   308 
   309 /** first element */
   310 #define isingleListFirst(name) dArrayAt(&(name)->list, (name)->head).elem
   311 #define isingleListHead isingleListFirst
   312 
   313 /** first previous node index (always null) */
   314 #define isingleListFirstPrevIdx(name) dArrayAt(&(name)->list, (name)->head).prev
   315 #define isingleListHeadPrev isingleListFirstPrev
   316 
   317 /** first node */
   318 #define isingleListFirstNode(name) dArrayAt(&(name)->list, (name)->head)
   319 #define isingleListHeadNode isingleListFirstNode
   320 
   321 /** first index */
   322 #define isingleListFirstIdx(name) (name)->head
   323 #define isingleListHeadIdx isingleListFirstIdx
   324 
   325 /** first node pointer */
   326 #define isingleListFirstPtr(name) dArrayPtr(&(name)->list, (name)->head)
   327 #define isingleListHeadPtr isingleListFirstPtr
   328 
   329 /** last element */
   330 #define isingleListLast(name) dArrayAt(&(name)->list, (name)->last).elem
   331 
   332 /** last previous node index */
   333 #define isingleListLastPrevIdx(name) dArrayAt(&(name)->list, (name)->last).prev
   334 
   335 /** last node */
   336 #define isingleListLastNode(name) dArrayAt(&(name)->list, (name)->last)
   337 
   338 /** last index */
   339 #define isingleListLastIdx(name) (name)->last
   340 
   341 /** last node pointer */
   342 #define isingleListLastPtr(name) dArrayPtr(&(name)->list, (name)->last)
   343 
   344 /** elem at node index */
   345 #define isingleListElem(name, nodeIndex) dArrayAt(&(name)->list, nodeIndex).elem
   346 
   347 /** previous index */
   348 #define isingleListPrevIdx(name, nodeIndex) dArrayAt(&(name)->list, nodeIndex).prev
   349 
   350 /** node at index */
   351 #define isingleListNode(name, nodeIndex) dArrayAt(&(name)->list, nodeIndex)
   352 
   353 /** node pointer at index */
   354 #define isingleListPtr(name, nodeIndex) dArrayPtr(&(name)->list, nodeIndex)
   355 
   356 /** node element (or use node.elem) */
   357 #define isingleListNodeElem(node) (node).elem
   358 
   359 /** previous index in node */
   360 #define isingleListNodePrev(node) (node).prev
   361 
   362 /** node element (or use node.elem) */
   363 #define isingleListNodePtrElem(node) (node)->elem
   364 
   365 /** previous index in node */
   366 #define isingleListNodePtrPrev(node) (node)->prev
   367 
   368 /** previous node at index, index must not be equal to head */
   369 #define isingleListPrevAt(name, nodeIndex) dArrayAt(&(name)->list, isingleListPrevIdx(name, nodeIndex))
   370 
   371 /** previous node */
   372 #define isingleListPrev(name, node) dArrayAt(&(name)->list, (node).prev)
   373 
   374 /** previous node pointer */
   375 #define isingleListPrevPtr(name, nodePtr) ({\
   376   dArrayElemPtrType(&(name)->list) UNIQVAR(res) = NULL;\
   377   if ((nodePtr)->prev != (name)->null) {\
   378     UNIQVAR(res) = dArrayPtr(&(name)->list, (nodePtr)->prev);\
   379   }\
   380   UNIQVAR(res);\
   381   })
   382 
   383 
   384 
   385 
   386 
   387 
   388 
   389 /** loop on indexes from last to head, to access the element use isingleListElem */
   390 #define isingleListForEachDown(name, index)\
   391   for(var index = isingleListLastIdx(name); index != (name)->null ; index = isingleListPrevIdx(name, index))
   392 
   393 /** loop node pointers from last to head, to access the elment use isingleListNodePtrElem(node) or (node)->elem */
   394 #define isingleListForEachNodeDown(name, node)\
   395   for(var node = isingleListLastPtr(name); node != NULL ; node = isingleListPrevPtr(name, node))
   396 
   397 /** loop element from last to head (the element data is copied) */
   398 #define isingleListForEachElemDown(name, element)\
   399   var UNIQVAR(idx) = isingleListLastIdx(name);\
   400   for(var element = isingleListLast(name); UNIQVAR(idx) != (name)->null ; UNIQVAR(idx) = isingleListPrevIdx(name, UNIQVAR(idx)), element = (UNIQVAR(idx) != (name)->null) ? isingleListElem(name, UNIQVAR(idx)) : element)
   401 
   402 /** loop element pointers from last to head, use *elemPtr to access the element data */
   403 #define isingleListForEachElemPDown(name, elemPtr)\
   404   var UNIQVAR(idx) = isingleListLastIdx(name);\
   405   for(var elemPtr = &isingleListLast(name); UNIQVAR(idx) != (name)->null ; UNIQVAR(idx) = isingleListPrevIdx(name, UNIQVAR(idx)), elemPtr = (UNIQVAR(idx) != (name)->null) ? &isingleListElem(name, UNIQVAR(idx)) : elemPtr)
   406 
   407 /** loop on indexes from startIndex to head, to access the element use isingleListElem */
   408 #define isingleListForEachFromDown(name, index, startIndex)\
   409   for(typeof((name)->null) index = startIndex; index != (name)->null ; index = isingleListPrevIdx(name, index))
   410 
   411 /** loop node pointers from startNode to head, to access the elment use isingleListNodePtrElem(node) or (node)->elem */
   412 #define isingleListForEachNodeFromDown(name, node, startNode)\
   413   for(isingleListNodeType(name) node = startNode; node != NULL ; node = isingleListPrevPtr(name, node))
   414 
   415 /** loop element from startIndex to head (the element data is copied) */
   416 #define isingleListForEachElemFromDown(name, element, startIndex)\
   417   typeof((name)->null) UNIQVAR(idx) = startIndex;\
   418   for(var element = isingleListLast(name); UNIQVAR(idx) != (name)->null ; UNIQVAR(idx) = isingleListPrevIdx(name, UNIQVAR(idx)), element = (UNIQVAR(idx) != (name)->null) ? isingleListElem(name, UNIQVAR(idx)) : element)
   419 
   420 /** loop element pointers from startIndex to head, use *elemPtr to access the element data */
   421 #define isingleListForEachElemPFromDown(name, elemPtr, startIndex)\
   422   typeof((name)->null) UNIQVAR(idx) = startIndex;\
   423   for(var elemPtr = &isingleListLast(name); UNIQVAR(idx) != (name)->null ; UNIQVAR(idx) = isingleListPrevIdx(name, UNIQVAR(idx)), elemPtr = (UNIQVAR(idx) != (name)->null) ? &isingleListElem(name, UNIQVAR(idx)) : elemPtr)
   424 
   425 
   426 
   427 
   428 
   429 
   430 /**
   431  * insert nodeToInsert index before referenceNode index
   432  */
   433 #define isingleListInsertBefore(name, referenceNodeIndex, nodeToInsertIndex) do{\
   434   typeof((name)->null) UNIQVAR(referenceNodeIdx)      = referenceNodeIndex;\
   435   typeof((name)->null) UNIQVAR(nodeToInsertIdx)       = nodeToInsertIndex;\
   436   /* save previous node index */\
   437   var                  UNIQVAR(tmp)                   = isingleListPrevIdx(name, UNIQVAR(referenceNodeIdx));\
   438   /* previous node in now nodeToInsert */\
   439   isingleListPrevIdx(name, UNIQVAR(referenceNodeIdx)) = UNIQVAR(nodeToInsertIdx);\
   440   /* connect rest of the list to nodeToInsert */\
   441   isingleListPrevIdx(name, UNIQVAR(nodeToInsertIdx))  = UNIQVAR(tmp);\
   442   if (UNIQVAR(tmp) == (name)->null) /* referenceNode was head node */ (name)->head = UNIQVAR(nodeToInsertIdx);\
   443   (name)->count++;\
   444   } while(0)
   445 
   446 #define isingleListInsertPrev isingleListInsertBefore
   447 
   448 /**
   449  * insert nodeToInsert index last
   450  */
   451 #define isingleListInsertLast(name, nodeToInsertIndex) do{\
   452   typeof((name)->null) UNIQVAR(nodeToInsertIdx) = nodeToInsertIndex;\
   453   if (isingleListIsEmpty(name)) {\
   454     /* list is empty, previous node is null and set both head and last */\
   455     isingleListPrevIdx(name, UNIQVAR(nodeToInsertIdx)) = (name)->null;\
   456     (name)->head = (name)->last                        = UNIQVAR(nodeToInsertIdx);\
   457   }\
   458   else {\
   459     /* last node is previous node for nodeToInsert */\
   460     isingleListPrevIdx(name, UNIQVAR(nodeToInsertIdx)) = (name)->last;\
   461     /* now last is nodeToInsert */\
   462     (name)->last                                       = UNIQVAR(nodeToInsertIdx);\
   463   }\
   464   (name)->count++;\
   465   } while(0)
   466 
   467 // // NO - cant insert before and after last
   468 // #define isingleListInsert(name, referenceNodeIndex, nodeToInsertIndex) do{\
   469 //   typeof((name)->null) UNIQVAR(refNodeIdx) = referenceNodeIndex;\
   470 //   if (UNIQVAR(refNodeIdx) != (name)->last) isingleListInsertBefore(name, UNIQVAR(refNodeIdx), nodeToInsertIndex);\
   471 //   else isingleListInsertLast(name, nodeToInsertIndex);\
   472 //   } while(0)
   473 
   474 
   475 // Internal
   476 // allocate a node
   477 #define isingleListAddNode(name) ({\
   478   typeof((name)->null) UNIQVAR(res) = (name)->null;\
   479   if (dArrayIsEmpty(&(name)->freeList)) {\
   480     /* create new node */\
   481     dArrayPush(&(name)->list);\
   482     UNIQVAR(res) = dArrayLastIndex(&(name)->list);\
   483   }\
   484   else {\
   485     /* reuse a free node */\
   486     UNIQVAR(res) = dArrayLast(&(name)->freeList);\
   487     dArrayDelLast(&(name)->freeList);\
   488   }\
   489   UNIQVAR(res);\
   490   })
   491 
   492 /**
   493  * add new node before referenceNode index
   494  *
   495  * \return
   496  *   resultNode index: access element in node with isingleListElem(name, resultNode)
   497  */
   498 #define isingleListAddBefore(name, referenceNodeIndex) ({\
   499   typeof((name)->null) UNIQVAR(res) = isingleListAddNode(name);\
   500   isingleListInsertBefore(name, referenceNodeIndex, UNIQVAR(res));\
   501   UNIQVAR(res);\
   502   })
   503 
   504 #define isingleListAddPrev isingleListAddBefore
   505 
   506 /** add new node index after last
   507  *
   508  * \return
   509  *   resultNode new node index after last (new last node)
   510  */
   511 #define isingleListAddLast(name) ({\
   512   typeof((name)->null) UNIQVAR(res) = isingleListAddNode(name);\
   513   isingleListInsertLast(name, UNIQVAR(res));\
   514   UNIQVAR(res);\
   515   })
   516 
   517 // // NO - cant insert before and after last
   518 // #define isingleListAdd(name, referenceNodeIndex) ({\
   519 //   typeof((name)->null) UNIQVAR(res) = isingleListAddNode(name);\
   520 //   isingleListInsert(name, referenceNodeIndex, UNIQVAR(res));\
   521 //   UNIQVAR(res);\
   522 //   })
   523 
   524 
   525 
   526 
   527 
   528 /**
   529  * write the isingleList content to filename file
   530  * No NULL checks are done on the parameters
   531  *
   532  * \param
   533  *    filename file name string
   534  */
   535 #define isingleListWriteFilename(name, filename) do {\
   536   FILE *UNIQVAR(f) = fopen(filename, "w");\
   537   if (UNIQVAR(f)) {\
   538     isingleListForEachDown(name, UNIQVAR(i)) {\
   539       fwrite(&isingleListElem(name, UNIQVAR(i)), 1, sizeof(isingleListElem(name, 0)), UNIQVAR(f));\
   540     }\
   541     fclose(UNIQVAR(f));\
   542   }\
   543   } while(0)
   544 
   545 /**
   546  * write the isingleList content to disk
   547  * No NULL checks are done on the parameters
   548  *
   549  * \param
   550  *    file already opened file
   551  */
   552 #define isingleListWrite(name, file) do {\
   553   isingleListForEachDown(name, UNIQVAR(i)) {\
   554     fwrite(&isingleListElem(name, UNIQVAR(i)), 1, sizeof(isingleListElem(name, 0)), file);\
   555   }\
   556   } while(0)
   557 
   558 /**
   559  * read a isingleList from filename file
   560  * No NULL checks are done on the parameters
   561  *
   562  * \param
   563  * filename file name string
   564  */
   565 #define isingleListReadFilename(name, filename) do {\
   566   if (fileExists(filename)) {\
   567     size_t UNIQVAR(sz) = fileSize(filename);\
   568     const size_t UNIQVAR(elemSz) = sizeof(isingleListElem(name, 0));\
   569     if ((UNIQVAR(sz) % UNIQVAR(elemSz))) /* file size not a multiple of elem size, wrong*/ break;\
   570     UNIQVAR(sz) /= UNIQVAR(elemSz);\
   571     if (!UNIQVAR(sz)) /* there is no element to load*/ break;\
   572     FILE *UNIQVAR(f) = fopen(filename, "r");\
   573     if (UNIQVAR(f)) {\
   574       isingleListPush(name);\
   575       fread(&isingleListLast(name), 1, UNIQVAR(elemSz), UNIQVAR(f));\
   576       typeof((name)->null) UNIQVAR(insertBefore) = (name)->last;\
   577       range(UNIQVAR(i), UNIQVAR(sz)-1) {\
   578         UNIQVAR(insertBefore) = isingleListAddBefore(name, UNIQVAR(insertBefore));\
   579         fread(&isingleListElem(name, UNIQVAR(insertBefore)), 1, UNIQVAR(elemSz), UNIQVAR(f));\
   580       }\
   581       fclose(UNIQVAR(f));\
   582     }\
   583   }\
   584   } while(0)
   585 
   586 /**
   587  * read a isingleList from disk
   588  * No NULL checks are done on the parameters
   589  *
   590  * \param
   591  *    file already opened file
   592  */
   593 #define isingleListRead(name, file) do {\
   594   fseek(file, 0 , SEEK_END);\
   595   size_t UNIQVAR(sz) = ftell(file);\
   596   fseek(file, 0 , SEEK_SET);\
   597   const size_t UNIQVAR(elemSz) = sizeof(isingleListElem(name, 0));\
   598   if ((UNIQVAR(sz) % UNIQVAR(elemSz))) /* file size not a multiple of elem size, wrong*/ break;\
   599   UNIQVAR(sz) /= UNIQVAR(elemSz);\
   600   if (!UNIQVAR(sz)) /* there is no element to load*/ break;\
   601   isingleListPush(name);\
   602   fread(&isingleListLast(name), 1, UNIQVAR(elemSz), file);\
   603   typeof((name)->null) UNIQVAR(insertBefore) = (name)->last;\
   604   range(UNIQVAR(i), UNIQVAR(sz)-1) {\
   605     UNIQVAR(insertBefore) = isingleListAddBefore(name, UNIQVAR(insertBefore));\
   606     fread(&isingleListElem(name, UNIQVAR(insertBefore)), 1, UNIQVAR(elemSz), file);\
   607   }\
   608   } while(0)
   609 
   610 // vim: set expandtab ts=2 sw=2: