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: