6e110e17b5f86e74ebc45a65306229cd7e62ed12
[asterisk/asterisk.git] / addons / ooh323c / src / dlist.c
1 /*
2  * Copyright (C) 1997-2005 by Objective Systems, Inc.
3  *
4  * This software is furnished under an open source license and may be 
5  * used and copied only in accordance with the terms of this license. 
6  * The text of the license may generally be found in the root 
7  * directory of this installation in the COPYING file.  It 
8  * can also be viewed online at the following URL:
9  *
10  *   http://www.obj-sys.com/open/license.html
11  *
12  * Any redistributions of this file including modified versions must 
13  * maintain this copyright notice.
14  *
15  *****************************************************************************/
16
17 #include "asterisk.h"
18 #include "asterisk/lock.h"
19
20 #include "ooasn1.h"
21
22 void dListInit (DList* pList)
23 {
24    if (pList) {
25       pList->count = 0;
26       pList->head = (DListNode*) 0;
27       pList->tail = (DListNode*) 0;
28    }
29 }
30
31 DListNode* dListAppend (OOCTXT* pctxt, DList* pList, void* pData)
32 {
33    DListNode* pListNode = (DListNode*) 
34       memAlloc (pctxt, sizeof(DListNode));
35
36    if (0 != pListNode) {
37       pListNode->data = pData;
38       pListNode->next = (DListNode*) 0;
39       if (0 != pList->tail) {
40          pList->tail->next = pListNode;
41          pListNode->prev = pList->tail;
42       }
43       if (0 == pList->head) {
44          pList->head = pListNode;
45          pListNode->prev = (DListNode*) 0;
46       }
47       pList->tail = pListNode;
48       pList->count++;
49    }
50
51    return pListNode;
52 }
53
54 DListNode* dListAppendNode (OOCTXT* pctxt, DList* pList, void* pData)
55 {
56    DListNode* pListNode = 
57       (DListNode*) (((char*)pData) - sizeof(DListNode));
58
59    if (0 != pListNode) {
60       pListNode->data = pData;
61       pListNode->next = (DListNode*) 0;
62       if (0 != pList->tail) {
63          pList->tail->next = pListNode;
64          pListNode->prev = pList->tail;
65       }
66       if (0 == pList->head) {
67          pList->head = pListNode;
68          pListNode->prev = (DListNode*) 0;
69       }
70       pList->tail = pListNode;
71       pList->count++;
72    }
73
74    return pListNode;
75 }
76
77 /* Delete the head node from the list and return the data item stored   */
78 /* in that node..                                                       */
79
80 void* dListDeleteHead (OOCTXT* pctxt, DList* pList)
81 {
82    DListNode* pNode = (0 != pList) ? pList->head : 0;
83    if (0 != pNode) {
84       void* pdata = pNode->data;
85       dListRemove (pList, pNode);
86       memFreePtr (pctxt, pNode);
87       return pdata;
88    }
89    return 0;
90 }
91
92 /* Free all nodes, but not the data */
93 void dListFreeNodes (OOCTXT* pctxt, DList* pList)
94 {
95    DListNode* pNode, *pNextNode;
96
97    for (pNode = pList->head; pNode != 0; pNode = pNextNode) {
98       pNextNode = pNode->next;
99       memFreePtr (pctxt, pNode);
100    }
101    pList->count = 0;
102    pList->head = pList->tail = 0;
103 }
104
105 /* Free all nodes and their data */
106 void dListFreeAll (OOCTXT* pctxt, DList* pList)
107 {
108    DListNode* pNode, *pNextNode;
109
110    for (pNode = pList->head; pNode != 0; pNode = pNextNode) {
111       pNextNode = pNode->next;
112       
113       memFreePtr (pctxt, pNode->data);
114       memFreePtr (pctxt, pNode);
115    }
116    pList->count = 0;
117    pList->head = pList->tail = 0;
118 }
119
120 /* Remove node from list. Node is not freed */
121 void dListRemove (DList* pList, DListNode* node)
122 {
123    if(node->next != 0) {
124       node->next->prev = node->prev;
125    }
126    else { /* tail */
127       pList->tail = node->prev;
128    }
129    if(node->prev != 0) {
130       node->prev->next = node->next;
131    }
132    else { /* head */
133       pList->head = node->next;
134    }
135    pList->count--;
136 }
137
138 void dListFindAndRemove(DList* pList, void *data)
139 {
140    DListNode *pNode, *pNextNode;
141    for(pNode = pList->head; pNode !=0; pNode = pNextNode){
142       pNextNode = pNode->next;
143       if(pNode->data == data) /* pointer comparison*/
144          break;
145    }
146    if(pNode)
147       dListRemove(pList, pNode);
148 }
149     
150 DListNode* dListFindByIndex (DList* pList, int index) 
151 {
152    DListNode* curNode;
153    int i;
154
155    if(index >= (int)pList->count) return 0;
156    for(i = 0, curNode = pList->head; i < index && curNode != 0; i++) {
157       curNode = curNode->next;
158    }
159    return curNode;
160 }
161
162 /* Insert item before given node */
163
164 DListNode* dListInsertBefore 
165 (OOCTXT* pctxt, DList* pList, DListNode* node, const void* pData)
166 {
167    DListNode* pListNode = (DListNode*) memAlloc (pctxt, sizeof(DListNode));
168   
169    if (0 != pListNode) {
170       pListNode->data = (void*)pData;
171
172       if (node == 0) { /* insert before end (as last element) */
173          pListNode->next = (DListNode*) 0;
174          if (0 != pList->tail) {
175             pList->tail->next = pListNode;
176             pListNode->prev = pList->tail;
177          }
178          if (0 == pList->head) {
179             pList->head = pListNode;
180             pListNode->prev = (DListNode*) 0;
181          }
182          pList->tail = pListNode;
183       }
184       else if (node == pList->head) { /* insert as head (head case) */
185          pListNode->next = pList->head;
186          pListNode->prev = (DListNode*) 0;
187          if(pList->head != 0) {
188             pList->head->prev = pListNode;
189          }
190          if(pList->tail == 0) {
191             pList->tail = pListNode;
192          }
193          pList->head = pListNode;
194       }
195       else { /* other cases */
196          pListNode->next = node;
197          pListNode->prev = node->prev;
198          node->prev = pListNode;
199          /* here, pListNode->prev always should be non-zero,
200           * because if pListNode->prev is zero - it is head case (see above).
201           */
202          pListNode->prev->next = pListNode;
203       }
204
205       pList->count++;
206    }
207
208    return pListNode;
209 }
210
211 /* Insert item after given node */
212
213 DListNode* dListInsertAfter 
214 (OOCTXT* pctxt, DList* pList, DListNode* node, const void* pData)
215 {
216    DListNode* pListNode = (DListNode*) memAlloc (pctxt, sizeof(DListNode));
217
218    if (0 != pListNode) {
219       pListNode->data = (void*)pData;
220
221       if (node == 0) { /* insert as head (as first element) */
222          pListNode->next = pList->head;
223          pListNode->prev = (DListNode*) 0;
224          if (pList->head != 0) {
225             pList->head->prev = pListNode;
226          }
227          if (pList->tail == 0) {
228             pList->tail = pListNode;
229          }
230          pList->head = pListNode;
231       }
232       else if (node == pList->tail) { /* insert as tail (as last element) */
233          pListNode->next = (DListNode*) 0;
234          if (0 != pList->tail) {
235             pList->tail->next = pListNode;
236             pListNode->prev = pList->tail;
237          }
238          if (0 == pList->head) {
239             pList->head = pListNode;
240             pListNode->prev = (DListNode*) 0;
241          }
242          pList->tail = pListNode;
243       }
244       else { /* other cases */
245          pListNode->next = node->next;
246          pListNode->prev = node;
247          node->next = pListNode;
248          /* here, pListNode->next always should be non-zero,
249           * because if pListNode->next is zero - it is tail case (see above).
250           */
251          pListNode->next->prev = pListNode;
252       }
253
254       pList->count++;
255    }
256
257    return pListNode;
258 }
259