librnr  1.14.5
RoadNarrows Robotics Common Library 1
dlistvoid.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Common Library 1
4 //
5 // Library: librnr
6 //
7 // File: dlistvoid.c
8 //
9 /*! \file
10  *
11  * \brief Doubly linked list (dlist) of void pointers definitions.
12  *
13  * \author Robin Knight (robin.knight@roadnarrows.com)
14  *
15  * \pkgcopyright{2005-2018,RoadNarrows LLC.,http://www.roadnarrows.com}
16  *
17  * \EulaBegin
18  * See the README and EULA files for any copyright and licensing information.
19  * \EulaEnd
20  */
21 ////////////////////////////////////////////////////////////////////////////////
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "rnr/rnrconfig.h"
28 #include "rnr/dlist.h"
29 #include "rnr/dlistvoid.h"
30 #include "rnr/log.h"
31 #include "rnr/new.h"
32 
33 
34 // ---------------------------------------------------------------------------
35 // Private Interface
36 // ---------------------------------------------------------------------------
37 
38 /*!
39  * \brief Unit Tests (define to build test main)
40  */
41 #if defined(unittestDListVoid) && !defined(debugDListVoid)
42 #define debugDListVoid ///< UT needs debugging code
43 #endif
44 
45 /*!
46  * \brief Doubly linked list head structure.
47  */
49 {
50  dnode_t m_dnodeHead; ///< head of dlist
51  int m_nNumNodes; ///< number of nodes in dlist
52  DListVoidFuncDataCmp_T m_fnDataCmp; ///< data compare function
53  DListVoidFuncDataDelete_T m_fnDataDelete; ///< data delete function
54 };
55 
56 /*!
57  * \brief Doubly linked list node structure.
58  */
60 {
61  dnode_t m_dnode; ///< dlist pointers
62  void *m_pData; ///< user data
63 };
64 
65 
66 //
67 // Helper Macros
68 //
69 
70 /*!
71  * \brief Get embedding node DListVoidNode_T
72  * \param dnode dnode_t *
73  * \return DListVoidNode_T* 'pointed to' by dnode_t*
74  */
75 #define DLISTVOID_ENTRY(dnode) dlist_entry(dnode, DListVoidNode_T, m_dnode)
76 
77 /*!
78  * \brief Test if DListVoid_T* holds the empty list.
79  * \param dvoidhead dnode_t *
80  * \return True (non-zero) if list is empty, 0 otherwise.
81  */
82 #define DLISTVOID_IS_EMPTY(dvoidhead) \
83  dlist_is_empty(&((dvoidhead)->m_dnodeHead))
84 
85 /*!
86  * \brief Test if node is at end-of-list.
87  * \param dvoidhead dnode_t *
88  * \param pdnode dnode_t *
89  * \return True (non-zero) if at end-of-list, 0 otherwise.
90  */
91 #define DLISTVOID_IS_EOL(dvoidhead, pdnode) \
92  ((pdnode) == &((dvoidhead)->m_dnodeHead))
93 
94 
95 
96 // ---------------------------------------------------------------------------
97 // Public Interface
98 // ---------------------------------------------------------------------------
99 
100 /*!
101  * \brief Allocate and initialize new empty dlist.
102  *
103  * \param fnDataCmp User-supplied data comparator function.
104  * NULL will disable some functions such as searches.
105  * \param fnDataDelete User-supplied data deallocator.
106  * NULL will cause user data not to be deleted.
107  *
108  * \return Returns pointer to new dlist (head) on success.
109  */
111  DListVoidFuncDataDelete_T fnDataDelete)
112 {
113  DListVoid_T *pHead;
114 
115  LOGDIAG4CALL(_TPTR(fnDataCmp), _TPTR(fnDataDelete));
116 
117  // allocate head
118  pHead = NEW(DListVoid_T);
119 
120  // initialize data
122  pHead->m_nNumNodes = 0;
123  pHead->m_fnDataCmp = fnDataCmp;
124  pHead->m_fnDataDelete = fnDataDelete;
125 
126  LOGDIAG4(_TPTR(pHead));
127 
128  return pHead;
129 }
130 
131 /*!
132  * \brief Delete entire dlist.
133  *
134  * All user data are deleted with a per node callback to the user-supplied
135  * data delete function, if any. All nodes in the dlist and the dlist itself
136  * will be deleted. The dlist pointer will no longer be valid after this call.
137  *
138  * \param pHead Pointer to dlist (head).
139  */
141 {
142  LOGDIAG4CALL(_TPTR(pHead));
143 
144  if( pHead == NULL )
145  {
146  return;
147  }
148 
150  delete(pHead);
151 }
152 
153 /*!
154  * \brief Unlink and delete all nodes and data from dlist, leaving dlist empty.
155  *
156  * User data are deleted with a per node callback to the user-supplied
157  * data delete function, if any.
158  *
159  * \param pHead Pointer to dlist (head).
160  */
162 {
163  dnode_t *p, *q, *head;
164 
165  LOGDIAG4CALL(_TPTR(pHead));
166 
167  if( pHead == NULL )
168  {
169  return;
170  }
171 
172  head = &(pHead->m_dnodeHead);
173 
174  dlist_for_each_safe(p, q, head)
175  {
177  }
178 }
179 
180 /*!
181  * \brief Unlink node from the dlist and delete the node and it's attached
182  * user data.
183  *
184  * User data are deleted with a callback to the user-supplied data delete
185  * function, if any.
186  *
187  * \param pHead Pointer to dlist (head).
188  * \param pNode Pointer to node to be deleted.
189  */
191 {
192  LOGDIAG4CALL(_TPTR(pHead), _TPTR(pNode));
193 
194  CHKPTR(pHead);
195  CHKPTR(pNode);
196 
197  if( DLISTVOID_IS_EMPTY(pHead) )
198  {
199  LOGERROR("dlist is empty");
200  return;
201  }
202 
203  // remove from list
204  dlist_delete(&pNode->m_dnode);
205 
206  // free any data by value
207  if( pHead->m_fnDataDelete != NULL )
208  {
209  pHead->m_fnDataDelete(pNode->m_pData);
210  }
211 
212  // free up node
213  delete(pNode);
214 
215  pHead->m_nNumNodes--;
216 }
217 
218 /*!
219  * \brief Unlink the node from the dlist at the given index and delete it and
220  * it's attached user data.
221  *
222  * User data are deleted with a callback to the user-supplied data delete
223  * function, if any.
224  *
225  * \param pHead Pointer to dlist (head).
226  * \param iIndex Index to dlist entry to delete.
227  */
228 void DListVoidDeleteNodeAt(DListVoid_T *pHead, int iIndex)
229 {
230  DListVoidNode_T *pNode;
231 
232  LOGDIAG4CALL(_TPTR(pHead), _TINT(iIndex));
233 
234  CHKPTR(pHead);
235 
236  // get node to delete
237  if( (pNode = DListVoidGetNodeAt(pHead, iIndex)) != NULL )
238  {
239  DListVoidDeleteNode(pHead, pNode);
240  }
241 }
242 
243 /*!
244  * \brief Unlink the node from the dlist at the given index.
245  *
246  * The node and it's attached data are not deleted.
247  *
248  * \param pHead Pointer to dlist (head).
249  * \param iIndex Index to dlist entry to unlink.
250  *
251  * \return Returns pointer to unlinked node on success, NULL on failure.
252  */
254 {
255  DListVoidNode_T *pNode;
256 
257  LOGDIAG4CALL(_TPTR(pHead), _TINT(iIndex));
258 
259  CHKPTR(pHead, NULL);
260 
261  // get node to delete
262  if( (pNode = DListVoidGetNodeAt(pHead, iIndex)) != NULL )
263  {
264  // remove from list
265  dlist_delete(&pNode->m_dnode);
266 
267  pHead->m_nNumNodes--;
268 
269  return pNode;
270  }
271  else
272  {
273  return NULL;
274  }
275 }
276 
277 /*!
278  * \brief Unlink the user data from the dlist at the given index.
279  *
280  * The node is deleted, but not the attached data.
281  *
282  * \param pHead Pointer to dlist (head).
283  * \param iIndex Index to dlist entry to unlink.
284  *
285  * \return Returns void* to user data on success, NULL on failure.
286  */
287 void *DListVoidUnlinkDataAt(DListVoid_T *pHead, int iIndex)
288 {
289  DListVoidNode_T *pNode;
290  void *pData;
291 
292  LOGDIAG4CALL(_TPTR(pHead), _TINT(iIndex));
293 
294  CHKPTR(pHead, NULL);
295 
296  // get node to delete
297  if( (pNode = DListVoidGetNodeAt(pHead, iIndex)) != NULL )
298  {
299  pData = pNode->m_pData;
300 
301  // remove from list
302  dlist_delete(&pNode->m_dnode);
303 
304  // free up node, but not the data
305  delete(pNode);
306 
307  pHead->m_nNumNodes--;
308 
309  return pData;
310  }
311  else
312  {
313  return NULL;
314  }
315 }
316 
317 /*!
318  * \brief Attach user data to a new node and link to the end of dlist.
319  *
320  * \param pHead Pointer to dlist (head).
321  * \param pData Pointer to user (allocated) data.
322  *
323  * \return Returns pointer to new node on success, NULL on failure.
324  */
326 {
327  DListVoidNode_T *pNode;
328 
329  LOGDIAG4CALL(_TPTR(pHead), _TPTR(pData));
330 
331  CHKPTR(pHead, NULL);
332 
333  // allocate node
334  pNode = NEW(DListVoidNode_T);
335 
336  // attach data
337  pNode->m_pData = pData;
338 
339  // insert into list
340  dlist_append(&pNode->m_dnode, &pHead->m_dnodeHead);
341 
342  pHead->m_nNumNodes++;
343 
344  LOGDIAG4(_TPTR(pNode));
345 
346  return pNode;
347 }
348 
349 /*!
350  * \brief Attach the user data to a new node and link to the start of dlist.
351  *
352  * \param pHead Pointer to dlist (head).
353  * \param pData Pointer to user (allocated) data.
354  *
355  * \return Returns pointer to new node on success, NULL on failure.
356  */
358 {
359  DListVoidNode_T *pNode;
360 
361  LOGDIAG4CALL(_TPTR(pHead), _TPTR(pData));
362 
363  CHKPTR(pHead, NULL);
364 
365  // allocate node
366  pNode = NEW(DListVoidNode_T);
367 
368  // attach data
369  pNode->m_pData = pData;
370 
371  // insert into list
372  dlist_prepend(&pNode->m_dnode, &pHead->m_dnodeHead);
373 
374  pHead->m_nNumNodes++;
375 
376  LOGDIAG4(_TPTR(pNode));
377 
378  return pNode;
379 }
380 
381 /*!
382  * \brief Attach the user data to a new node and insert before the dlist index.
383  *
384  * The special index value DLIST_INSERT_AT_END will insert at end-of-list
385  * (append).
386  *
387  * \param pHead Pointer to dlist (head).
388  * \param iIndex Index to dlist entry where insertion occurs.
389  * \param pData Pointer to user (allocated) data.
390  *
391  * \return Returns pointer to new node on success, NULL on failure.
392  */
393 DListVoidNode_T *DListVoidInsert(DListVoid_T *pHead, int iIndex, void *pData)
394 {
395  DListVoidNode_T *pNext;
396  DListVoidNode_T *pNode;
397 
398  LOGDIAG4CALL(_TPTR(pHead), _TINT(iIndex), _TPTR(pData));
399 
400  CHKPTR(pHead, NULL);
401 
402  if( iIndex == 0 )
403  {
404  return DListVoidPrepend(pHead, pData);
405  }
406  else if( (iIndex == DLIST_INSERT_AT_END) ||
407  (iIndex == DListVoidCount(pHead)) )
408  {
409  return DListVoidAppend(pHead, pData);
410  }
411 
412  // get insertion point
413  if( (pNext = DListVoidGetNodeAt(pHead, iIndex)) == NULL )
414  {
415  return NULL;
416  }
417 
418  // allocate node
419  pNode = NEW(DListVoidNode_T);
420 
421  // attach data
422  pNode->m_pData = pData;
423 
424  // insert into list
425  _dlist_add(&pNode->m_dnode, pNext->m_dnode.prev, &pNext->m_dnode);
426 
427  pHead->m_nNumNodes++;
428 
429  LOGDIAG4(_TPTR(pNode));
430 
431  return pNode;
432 }
433 
434 /*!
435  * \brief Get the node at the given dlist index.
436  *
437  * \param pHead Pointer to dlist (head).
438  * \param iIndex Index to dlist entry to find.
439  *
440  * \return Returns node at index on success, NULL on failure.
441  */
442 void *DListVoidGetNodeAt(DListVoid_T *pHead, int iIndex)
443 {
444  int nCnt;
445  dnode_t *p, *q, *head;
446 
447  LOGDIAG4CALL(_TPTR(pHead), _TINT(iIndex));
448 
449  CHKPTR(pHead, NULL);
450 
451  nCnt = pHead->m_nNumNodes;
452 
453  if( iIndex == DLIST_INSERT_AT_END )
454  {
455  iIndex = nCnt - 1;
456  }
457 
458  if( (iIndex < 0) || (iIndex >= nCnt) )
459  {
460  LOGERROR("%d index is out of range", iIndex);
461  }
462 
463  head = &(pHead->m_dnodeHead);
464 
465  dlist_for_each_safe(p, q, head)
466  {
467  if( iIndex-- == 0 )
468  {
469  return DLISTVOID_ENTRY(p);
470  }
471  }
472 
473  return NULL;
474 }
475 
476 /*!
477  * \brief Get the user data from the given node.
478  *
479  * \param pNode Pointer to node with data.
480  *
481  * \return Returns void* to user data on success, NULL on failure.
482  */
484 {
485  return pNode == NULL? NULL: pNode->m_pData;
486 }
487 
488 /*!
489  * \brief Get the user data from the dlist at the given index.
490  *
491  * \param pHead Pointer to dlist (head).
492  * \param iIndex Index to dlist entry.
493  *
494  * \return Returns void* to user data on success, NULL on failure.
495  */
496 void *DListVoidGetDataAt(DListVoid_T *pHead, int iIndex)
497 {
498  DListVoidNode_T *pNode;
499 
500  if( (pNode = DListVoidGetNodeAt(pHead, iIndex)) != NULL )
501  {
502  return DListVoidGetData(pNode);
503  }
504  else
505  {
506  return NULL;
507  }
508 }
509 
510 /*!
511  * \brief Get the number of nodes in dlist.
512  *
513  * \param pHead Pointer to dlist (head).
514  *
515  * \return Number of nodes in dlist.
516  */
518 {
519  return pHead == NULL? 0: pHead->m_nNumNodes;
520 }
521 
522 /*!
523  * \brief Initialize dlist iterator and return the first node in dlist.
524  *
525  * \param pHead Pointer to dlist (head).
526  * \param pIter Pointer to iterator.
527  *
528  * \return Returns first node in dlist on success, NULL if dlist empty or
529  * on error.
530  */
532  DListVoidIter_T *pIter)
533 {
534  CHKPTR(pHead, NULL);
535  CHKPTR(pIter, NULL);
536 
537  pIter->m_pHead = pHead;
538  pIter->m_pThis = pHead->m_dnodeHead.next;
539  pIter->m_pNext = ((dnode_t *)(pIter->m_pThis))->next;
540 
541  if( DLISTVOID_IS_EMPTY(pHead) )
542  {
543  return NULL;
544  }
545  else
546  {
547  return DLISTVOID_ENTRY(((dnode_t *)(pIter->m_pThis)));
548  }
549 }
550 
551 /*!
552  * \brief Get the next iterated node in dlist.
553  *
554  * \param pIter Pointer to initialized iterator.
555  *
556  * \return Returns next node in dlist on success, NULL if if at end of list or
557  * on error.
558  */
560 {
561  CHKPTR(pIter, NULL);
562  CHKPTR(pIter->m_pHead, NULL);
563  CHKPTR(pIter->m_pNext, NULL);
564 
565  // end of list
566  if( DLISTVOID_IS_EOL(pIter->m_pHead, pIter->m_pNext) )
567  {
568  return NULL;
569  }
570  else
571  {
572  pIter->m_pThis = pIter->m_pNext;
573  pIter->m_pNext = ((dnode_t *)(pIter->m_pThis))->next;
574  return DLISTVOID_ENTRY(((dnode_t *)(pIter->m_pThis)));
575  }
576 }
577 
578 /*!
579  * \brief Initialize dlist iterator and return the last node in dlist.
580  *
581  * \param pHead Pointer to dlist (head).
582  * \param pIter Pointer to iterator.
583  *
584  * \return Returns last node in dlist on success, NULL if dlist empty or
585  * on error.
586  */
588  DListVoidIter_T *pIter)
589 {
590  CHKPTR(pHead, NULL);
591  CHKPTR(pIter, NULL);
592 
593  pIter->m_pHead = pHead;
594  pIter->m_pThis = pHead->m_dnodeHead.prev;
595  pIter->m_pNext = ((dnode_t *)(pIter->m_pThis))->prev;
596 
597  if( DLISTVOID_IS_EMPTY(pHead) )
598  {
599  return NULL;
600  }
601  else
602  {
603  return DLISTVOID_ENTRY(((dnode_t *)(pIter->m_pThis)));
604  }
605 }
606 
607 /*!
608  * \brief Get the previous iterated node in dlist.
609  *
610  * \param pIter Pointer to initialized iterator.
611  *
612  * \return Returns previous node in dlist on success,
613  * NULL if if at end of list or on error.
614  */
616 {
617  CHKPTR(pIter, NULL);
618  CHKPTR(pIter->m_pHead, NULL);
619  CHKPTR(pIter->m_pNext, NULL);
620 
621  // end of list
622  if( DLISTVOID_IS_EOL(pIter->m_pHead, pIter->m_pNext) )
623  {
624  return NULL;
625  }
626  else
627  {
628  pIter->m_pThis = pIter->m_pNext;
629  pIter->m_pNext = ((dnode_t *)(pIter->m_pThis))->prev;
630  return DLISTVOID_ENTRY(((dnode_t *)(pIter->m_pThis)));
631  }
632 }
633 
634 /*!
635  * \brief Find the first node with the matching data.
636  *
637  * The user provided comparator function is used, if any.
638  *
639  * \param pHead Pointer to dlist (head).
640  * \param pData Pointer to data to find.
641  *
642  * \return Returns first node with mathcing data on success, NULL if
643  * no matches or on error.
644  */
645 DListVoidNode_T *DListVoidFindNode(DListVoid_T *pHead, const void *pData)
646 {
647  dnode_t *p, *q, *head;
648  DListVoidNode_T *pNode;
649 
650  LOGDIAG4CALL(_TPTR(pHead), _TPTR(pData));
651 
652  CHKPTR(pHead, NULL);
653 
654  if( pHead->m_fnDataCmp == NULL )
655  {
656  return NULL;
657  }
658 
659  head = &(pHead->m_dnodeHead);
660 
661  dlist_for_each_safe(p, q, head)
662  {
663  pNode = DLISTVOID_ENTRY(p);
664  if( !pHead->m_fnDataCmp(pData, pNode->m_pData) )
665  {
666  return pNode;
667  }
668  }
669  return NULL;
670 }
671 
672 /*!
673  * \brief Traverse dlist and print.
674  *
675  * \param pHead Pointer to dlist (head).
676  * \param fnDataPr User data printing fucntion.
677  * \param fp Output file pointer
678  */
680  FILE *fp)
681 {
682  dnode_t *p, *q, *head;
683  DListVoidNode_T *pNode;
684  int n;
685 
686  head = &(pHead->m_dnodeHead);
687  n = 0;
688 
689  dlist_for_each_safe(p, q, head)
690  {
691  pNode = DLISTVOID_ENTRY(p);
692  fprintf(fp, "Node %2d: ", n);
693  fnDataPr(fp, pNode->m_pData);
694  fprintf(fp, "\n");
695  ++n;
696  }
697 }
698 
699 
700 //-----------------------------------------------------------------------------
701 // Unit Test
702 //-----------------------------------------------------------------------------
703 
704 #ifdef unittestDListVoid
705 
706 #define UT_APP(p, s) DListVoidAppend(p, (void *)s, (size_t)(strlen(s)+1))
707 #define UT_PRT(p) DListVoidPrint(p, UTDListVoidTestPrintCallback, fp)
708 
709 static void UTDListVoidTestPrintCallback(FILE *fp, void *pData)
710 {
711  fprintf(fp, "'%s'", (char *)pData);
712 }
713 
714 void UTDListVoidTest()
715 {
716  const char *sTest = "DListVoidTest";
717  FILE *fp = stdout;
718  DListVoid_T *pHead;
719  DListVoidNode_T *pSav0, *pSav1, *pSav2;
720  DListVoidIter_T iter;
721 
722  pHead = DListVoidNew(DListDataBaseByValue, NULL);
723 
724  fprintf(fp, "%s: Appending apples, bananas, cherries, and dates\n", sTest);
725  pSav0 = UT_APP(pHead, "apples");
726  pSav1 = UT_APP(pHead, "bananas");
727  UT_APP(pHead, "cherries");
728  pSav2 = UT_APP(pHead, "dates");
729 
730  UT_PRT(pHead);
731 
732  fprintf(fp, "%s: Deleting bananas\n", sTest);
733  DListVoidDeleteNode(pHead, pSav1);
734  UT_PRT(pHead);
735 
736  fprintf(fp, "%s: Deleting apples and dates\n", sTest);
737  DListVoidDeleteNode(pHead, pSav0);
738  DListVoidDeleteNode(pHead, pSav2);
739  UT_PRT(pHead);
740 
741  fprintf(fp, "%s: Appending eggplant, fennel, and grapes\n", sTest);
742  UT_APP(pHead, "eggplant");
743  UT_APP(pHead, "fennel");
744  UT_APP(pHead, "grapes");
745  UT_PRT(pHead);
746 
747  fprintf(fp, "%s: Testing iterator\n", sTest);
748  for(pSav0=DListVoidIterFirst(pHead, &iter); pSav0 != NULL;
749  pSav0=DListVoidIterNext(&iter))
750  {
751  fprintf(fp, "%s: node data = '%s'\n",
752  sTest, (char *)DListVoidGetData(pSav0));
753  }
754 
755  fprintf(fp, "%s: Deleting all\n", sTest);
757 }
758 
759 #endif // unittestDListVoid
void * m_pNext
pointer to next dnode
Definition: dlistvoid.h:170
int(* DListVoidFuncDataCmp_T)(const void *, const void *)
Base: Node data comparator callback function type.
Definition: dlistvoid.h:141
DListVoidNode_T * DListVoidUnlinkNodeAt(DListVoid_T *pHead, int iIndex)
Unlink the node from the dlist at the given index.
Definition: dlistvoid.c:253
DListVoidNode_T * DListVoidIterNodeLast(DListVoid_T *pHead, DListVoidIter_T *pIter)
Initialize dlist iterator and return the last node in dlist.
Definition: dlistvoid.c:587
#define DLIST_NODE_INIT(node)
Initialize node links.
Definition: dlist.h:74
Base dlist iterator structure.
Definition: dlistvoid.h:166
#define _TINT(var)
int (decimal)
Definition: log.h:582
static void dlist_prepend(dnode_t *node, dnode_t *head)
prepend new node to head of list
Definition: dlist.h:109
void * DListVoidGetData(DListVoidNode_T *pNode)
Get the user data from the given node.
Definition: dlistvoid.c:483
#define DLISTVOID_IS_EOL(dvoidhead, pdnode)
Test if node is at end-of-list.
Definition: dlistvoid.c:91
void * DListVoidUnlinkDataAt(DListVoid_T *pHead, int iIndex)
Unlink the user data from the dlist at the given index.
Definition: dlistvoid.c:287
#define CHKPTR(p,...)
Checks validity of pointer.
Definition: log.h:651
#define NULL
null pointer
Definition: rnrconfig.h:199
dnode_t m_dnode
dlist pointers
Definition: dlistvoid.c:61
DListVoidNode_T * DListVoidPrepend(DListVoid_T *pHead, void *pData)
Attach the user data to a new node and link to the start of dlist.
Definition: dlistvoid.c:357
Memory allocation and deallocation declarations.
void * m_pThis
pointer to current dnode
Definition: dlistvoid.h:169
The doubly linked node structure.
Definition: dlist.h:57
DListVoidNode_T * DListVoidAppend(DListVoid_T *pHead, void *pData)
Attach user data to a new node and link to the end of dlist.
Definition: dlistvoid.c:325
DListVoidNode_T * DListVoidIterNodeNext(DListVoidIter_T *pIter)
Get the next iterated node in dlist.
Definition: dlistvoid.c:559
Doubly linked list base implementation.
void DListVoidDeleteNode(DListVoid_T *pHead, DListVoidNode_T *pNode)
Unlink node from the dlist and delete the node and it&#39;s attached user data.
Definition: dlistvoid.c:190
DListVoid_T * DListVoidNew(DListVoidFuncDataCmp_T fnDataCmp, DListVoidFuncDataDelete_T fnDataDelete)
Allocate and initialize new empty dlist.
Definition: dlistvoid.c:110
DListVoidNode_T * DListVoidIterNodePrev(DListVoidIter_T *pIter)
Get the previous iterated node in dlist.
Definition: dlistvoid.c:615
#define DLISTVOID_IS_EMPTY(dvoidhead)
Test if DListVoid_T* holds the empty list.
Definition: dlistvoid.c:82
static void dlist_delete(dnode_t *node)
deletes node from list
Definition: dlist.h:150
#define DLIST_INSERT_AT_END
Special dlist index value to insert before end-of-list.
Definition: dlistvoid.h:133
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
static void dlist_append(dnode_t *node, dnode_t *head)
append a new node to the in of the list
Definition: dlist.h:123
Doubly linked list (dlist) of data pointers #defines, types, and declarations.
#define NEW(T)
Allocate new type.
Definition: new.h:49
void(* DListVoidFuncDataDelete_T)(void *)
Base: Node data delete callback function type.
Definition: dlistvoid.h:146
struct dlist_node * next
next node in dlist
Definition: dlist.h:59
void DListVoidDeleteAllNodes(DListVoid_T *pHead)
Unlink and delete all nodes and data from dlist, leaving dlist empty.
Definition: dlistvoid.c:161
int DListVoidCount(DListVoid_T *pHead)
Get the number of nodes in dlist.
Definition: dlistvoid.c:517
RoadNarrows Robotics common configuration file.
void DListVoidDelete(DListVoid_T *pHead)
Delete entire dlist.
Definition: dlistvoid.c:140
DListVoidFuncDataDelete_T m_fnDataDelete
data delete function
Definition: dlistvoid.c:53
struct dlist_node * prev
previous node in dlist
Definition: dlist.h:60
#define dlist_for_each_safe(pos, npos, head)
safely iterate over a list
Definition: dlist.h:225
Unit Tests (define to build test main)
Definition: dlistvoid.c:48
#define DLISTVOID_ENTRY(dnode)
Get embedding node DListVoidNode_T.
Definition: dlistvoid.c:75
#define _TPTR(var)
pointer
Definition: log.h:587
#define LOGDIAG4CALL(...)
Standard Diagnostic Level 4 function call tracing.
Definition: log.h:442
DListVoidNode_T * DListVoidInsert(DListVoid_T *pHead, int iIndex, void *pData)
Attach the user data to a new node and insert before the dlist index.
Definition: dlistvoid.c:393
DListVoidNode_T * DListVoidIterNodeFirst(DListVoid_T *pHead, DListVoidIter_T *pIter)
Initialize dlist iterator and return the first node in dlist.
Definition: dlistvoid.c:531
void * DListVoidGetDataAt(DListVoid_T *pHead, int iIndex)
Get the user data from the dlist at the given index.
Definition: dlistvoid.c:496
Doubly linked list node structure.
Definition: dlistvoid.c:59
void DListVoidDeleteNodeAt(DListVoid_T *pHead, int iIndex)
Unlink the node from the dlist at the given index and delete it and it&#39;s attached user data...
Definition: dlistvoid.c:228
int m_nNumNodes
number of nodes in dlist
Definition: dlistvoid.c:51
DListVoidNode_T * DListVoidFindNode(DListVoid_T *pHead, const void *pData)
Find the first node with the matching data.
Definition: dlistvoid.c:645
static void _dlist_add(dnode_t *node, dnode_t *prev, dnode_t *next)
insert a new entry between two known consecutive entries
Definition: dlist.h:92
DListVoidFuncDataCmp_T m_fnDataCmp
data compare function
Definition: dlistvoid.c:52
void * DListVoidGetNodeAt(DListVoid_T *pHead, int iIndex)
Get the node at the given dlist index.
Definition: dlistvoid.c:442
void(* DListVoidFuncDataPrint_T)(FILE *, void *)
Base: Print node data callback function type.
Definition: dlistvoid.h:152
void * m_pData
user data
Definition: dlistvoid.c:62
dnode_t m_dnodeHead
head of dlist
Definition: dlistvoid.c:50
Logger declarations.
void DListVoidPrint(DListVoid_T *pHead, DListVoidFuncDataPrint_T fnDataPr, FILE *fp)
Traverse dlist and print.
Definition: dlistvoid.c:679
DListVoid_T * m_pHead
pointer to dlistvoid head
Definition: dlistvoid.h:168