This is Unofficial EPICS BASE Doxygen Site
ellLib.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * Author: John Winans (ANL)
11  * Date: 07-02-92
12  */
13 
14 #include <stdlib.h>
15 
16 #include "epicsAssert.h"
17 #include "ellLib.h"
18 
19  /****************************************************************************
20  *
21  * This function adds a node to the end of a linked list.
22  *
23  *****************************************************************************/
24 void ellAdd (ELLLIST *pList, ELLNODE *pNode)
25 {
26  pNode->next = NULL;
27  pNode->previous = pList->node.previous;
28 
29  if (pList->count)
30  pList->node.previous->next = pNode;
31  else
32  pList->node.next = pNode;
33 
34  pList->node.previous = pNode;
35  pList->count++;
36 
37  return;
38 }
39  /****************************************************************************
40  *
41  * This function concatinates the second linked list to the end of the first
42  * list. The second list is left empty. Either list (or both) lists may
43  * be empty at the begining of the operation.
44  *
45  *****************************************************************************/
46 void ellConcat (ELLLIST *pDstList, ELLLIST *pAddList)
47 {
48  if (pAddList->count == 0)
49  return; /* Add list is empty, nothing to add. */
50 
51  if (pDstList->count == 0) {
52  /* Destination list is empty... just transfer the add list over. */
53  pDstList->node.next = pAddList->node.next;
54  pDstList->node.previous = pAddList->node.previous;
55  pDstList->count = pAddList->count;
56  } else {
57  /* Destination list not empty... append the add list. */
58  pDstList->node.previous->next = pAddList->node.next;
59  pAddList->node.next->previous = pDstList->node.previous;
60  pDstList->node.previous = pAddList->node.previous;
61  pDstList->count += pAddList->count;
62  }
63 
64  pAddList->count = 0;
65  pAddList->node.next = NULL;
66  pAddList->node.previous = NULL;
67 
68  return;
69 }
70  /****************************************************************************
71  *
72  * This function deletes a specific node from a specified list;
73  *
74  *****************************************************************************/
75 void ellDelete (ELLLIST *pList, ELLNODE *pNode)
76 {
77  if (pList->node.previous == pNode)
78  pList->node.previous = pNode->previous;
79  else
80  pNode->next->previous = pNode->previous;
81 
82  if (pList->node.next == pNode)
83  pList->node.next = pNode->next;
84  else
85  pNode->previous->next = pNode->next;
86 
87  pList->count--;
88 
89  return;
90 }
91  /****************************************************************************
92  *
93  * This function extracts a sublist that starts with pStartNode and ends with
94  * pEndNode from pSrcList and places it in pDstList.
95  *
96  * WRS is unclear as to what happens when pDstList is non-empty at the start
97  * of the operation. We will place the extracted list at the END of pDstList
98  * when it is non-empty.
99  *
100  *****************************************************************************/
101 void ellExtract (ELLLIST *pSrcList, ELLNODE *pStartNode, ELLNODE *pEndNode, ELLLIST *pDstList)
102 {
103  ELLNODE *pnode;
104  int count;
105 
106  /* Cut the list out of the source list (update count later) */
107  if (pStartNode->previous != NULL)
108  pStartNode->previous->next = pEndNode->next;
109  else
110  pSrcList->node.next = pEndNode->next;
111 
112  if (pEndNode->next != NULL) {
113  pEndNode->next->previous = pStartNode->previous;
114  pEndNode->next = NULL;
115  }
116  else
117  pSrcList->node.previous = pStartNode->previous;
118 
119  /* Place the sublist into the destination list */
120  pStartNode->previous = pDstList->node.previous;
121  if (pDstList->count)
122  pDstList->node.previous->next = pStartNode;
123  else
124  pDstList->node.next = pStartNode;
125 
126  pDstList->node.previous = pEndNode;
127 
128  /* Adjust the counts */
129  pnode = pStartNode;
130  count = 1;
131  while(pnode != pEndNode)
132  {
133  pnode = pnode->next;
134  count++;
135  }
136  pSrcList->count -= count;
137  pDstList->count += count;
138 
139  return;
140 }
141  /****************************************************************************
142  *
143  * This function returns the first node in the specified list. The node is
144  * removed from the list. If the list is empty, NULL will be returned.
145  *
146  *****************************************************************************/
148 {
149  ELLNODE *pnode = pList->node.next;
150 
151  if (pnode != NULL)
152  ellDelete(pList, pnode);
153 
154  return pnode;
155 }
156 /****************************************************************************
157 *
158 * This function returns the last node in the specified list. The node is
159 * removed from the list. If the list is empty, NULL will be returned.
160 *
161 *****************************************************************************/
163 {
164  ELLNODE *pnode = pList->node.previous;
165 
166  if (pnode != NULL)
167  ellDelete(pList, pnode);
168 
169  return pnode;
170 }
171  /****************************************************************************
172  *
173  * This function inserts the specified node pNode after pPrev in the list
174  * plist. If pPrev is NULL, then pNode will be inserted at the head of the
175  * list.
176  *
177  *****************************************************************************/
178 void ellInsert (ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
179 {
180  if (pPrev != NULL) {
181  pNode->previous = pPrev;
182  pNode->next = pPrev->next;
183  pPrev->next = pNode;
184  } else {
185  pNode->previous = NULL;
186  pNode->next = plist->node.next;
187  plist->node.next = pNode;
188  }
189 
190  if (pNode->next == NULL)
191  plist->node.previous = pNode;
192  else
193  pNode->next->previous = pNode;
194 
195  plist->count++;
196 
197  return;
198 }
199  /****************************************************************************
200  *
201  * This function returns the nodeNum'th element in pList. If there is no
202  * nodeNum'th node in the list, NULL will be returned.
203  *
204  *****************************************************************************/
205 ELLNODE * ellNth (ELLLIST *pList, int nodeNum)
206 {
207  ELLNODE *pnode;
208 
209  if ((nodeNum < 1) || (pList->count == 0))
210  return NULL;
211 
212  if (nodeNum > pList->count/2) {
213  if (nodeNum > pList->count)
214  return NULL;
215 
216  pnode = pList->node.previous;
217  nodeNum = pList->count - nodeNum;
218  while(nodeNum) {
219  pnode = pnode->previous;
220  nodeNum--;
221  }
222  return pnode;
223  }
224 
225  pnode = pList->node.next;
226  while (--nodeNum > 0)
227  pnode = pnode->next;
228 
229  return pnode;
230 }
231  /****************************************************************************
232  *
233  * This function returns the node, nStep nodes forward from pNode. If there is
234  * no node that many steps from pNode, NULL will be returned.
235  *
236  *****************************************************************************/
237 ELLNODE * ellNStep (ELLNODE *pNode, int nStep)
238 {
239  if (nStep > 0) {
240  while ((pNode != NULL) && nStep) {
241  pNode = pNode->next;
242  nStep--;
243  }
244  } else {
245  while ((pNode != NULL) && nStep) {
246  pNode = pNode->previous;
247  nStep++;
248  }
249  }
250  return pNode;
251 }
252  /****************************************************************************
253  *
254  * This function returns the node number of pNode within pList. If the node is
255  * not in pList, -1 is returned. Note that the first node is 1.
256  *
257  *****************************************************************************/
258 int ellFind (ELLLIST *pList, ELLNODE *pNode)
259 {
260  ELLNODE *got = pList->node.next;
261  int count = 1;
262 
263  while ((got != pNode) && (got != NULL)) {
264  got = got->next;
265  count++;
266  }
267  if (got == NULL)
268  return -1;
269 
270  return count;
271 }
272  /****************************************************************************
273  *
274  * This function frees the nodes in a list. It makes the list into an empty
275  * list, and calls freeFunc() for all the nodes that are (were) in that list.
276  *
277  * NOTE: the nodes in the list are free()'d on the assumption that the node
278  * structures were malloc()'d one-at-a-time and that the ELLNODE structure is
279  * the first member of the parent structure.
280  *
281  *****************************************************************************/
282 void ellFree2 (ELLLIST *pList, FREEFUNC freeFunc)
283 {
284  ELLNODE *nnode = pList->node.next;
285  ELLNODE *pnode;
286 
287  while (nnode != NULL)
288  {
289  pnode = nnode;
290  nnode = nnode->next;
291  freeFunc(pnode);
292  }
293  pList->node.next = NULL;
294  pList->node.previous = NULL;
295  pList->count = 0;
296 }
297 
298  /****************************************************************************
299  *
300  * This function verifies that the list is consistent.
301  * joh 12-12-97
302  *
303  *****************************************************************************/
304 void ellVerify (ELLLIST *pList)
305 {
306  ELLNODE *pNode;
307  ELLNODE *pNext;
308  int count = 0;
309 
310  assert (pList);
311 
312  pNode = ellFirst(pList);
313  if (pNode) {
314  assert (ellPrevious(pNode) == NULL);
315  while (1) {
316  count++;
317  pNext = ellNext(pNode);
318  if (pNext) {
319  assert (ellPrevious(pNext) == pNode);
320  } else {
321  break;
322  }
323  pNode = pNext;
324  }
325  assert (ellNext(pNode) == NULL);
326  }
327 
328  assert (pNode == ellLast(pList));
329  assert (count == ellCount(pList));
330 }
ELLNODE * ellNStep(ELLNODE *pNode, int nStep)
Find the list node nStep steps away from a specified node.
Definition: ellLib.c:237
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
An EPICS-specific replacement for ANSI C&#39;s assert.
ELLNODE * ellNth(ELLLIST *pList, int nodeNum)
Find the Nth node in a list.
Definition: ellLib.c:205
void ellFree2(ELLLIST *pList, FREEFUNC freeFunc)
Free all the nodes in a list.
Definition: ellLib.c:282
ELLNODE * ellGet(ELLLIST *pList)
Deletes and returns the first node from a list.
Definition: ellLib.c:147
#define NULL
Definition: catime.c:38
#define ellPrevious(PNODE)
Find the previous node in list.
Definition: ellLib.h:104
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
int ellFind(ELLLIST *pList, ELLNODE *pNode)
Find the index of a specific node in a list.
Definition: ellLib.c:258
void(* FREEFUNC)(void *)
Pointer to free() for use by ellFree() macro.
Definition: ellLib.h:71
#define ellLast(PLIST)
Find the last node in list.
Definition: ellLib.h:94
List node type.
Definition: ellLib.h:45
struct ELLNODE * previous
Pointer to previous node in list.
Definition: ellLib.h:47
struct ELLNODE * next
Pointer to next node in list.
Definition: ellLib.h:46
int count
Number of nodes on the list.
Definition: ellLib.h:58
void ellInsert(ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
Inserts a node into a list immediately after a specific node.
Definition: ellLib.c:178
void ellConcat(ELLLIST *pDstList, ELLLIST *pAddList)
Concatenates a list to the end of another list. The list to be added is left empty. Either list (or both) can be empty at the beginning of the operation.
Definition: ellLib.c:46
ELLNODE * ellPop(ELLLIST *pList)
Deletes and returns the last node from a list.
Definition: ellLib.c:162
void ellExtract(ELLLIST *pSrcList, ELLNODE *pStartNode, ELLNODE *pEndNode, ELLLIST *pDstList)
Extract a sublist from a list.
Definition: ellLib.c:101
List header type.
Definition: ellLib.h:56
void ellVerify(ELLLIST *pList)
Verifies that the list is consistent.
Definition: ellLib.c:304
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
ELLNODE node
Pointers to the first and last nodes on list.
Definition: ellLib.h:57
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89