1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <com_android_nfc_list.h>
18 #include <com_android_nfc.h>
19 #include <pthread.h>
20 #include <errno.h>
21 #include <cutils/log.h>
22
23 #undef LOG_TAG
24 #define LOG_TAG "NFC_LIST"
25
listInit(listHead * pList)26 bool listInit(listHead* pList)
27 {
28 pList->pFirst = NULL;
29 if(pthread_mutex_init(&pList->mutex, NULL) == -1)
30 {
31 ALOGE("Mutex creation failed (errno=0x%08x)", errno);
32 return false;
33 }
34
35 return true;
36 }
37
listDestroy(listHead * pList)38 bool listDestroy(listHead* pList)
39 {
40 bool bListNotEmpty = true;
41 while (bListNotEmpty) {
42 bListNotEmpty = listGetAndRemoveNext(pList, NULL);
43 }
44
45 if(pthread_mutex_destroy(&pList->mutex) == -1)
46 {
47 ALOGE("Mutex destruction failed (errno=0x%08x)", errno);
48 return false;
49 }
50
51 return true;
52 }
53
listAdd(listHead * pList,void * pData)54 bool listAdd(listHead* pList, void* pData)
55 {
56 struct listNode* pNode;
57 struct listNode* pLastNode;
58 bool result;
59
60 /* Create node */
61 pNode = (struct listNode*)malloc(sizeof(listNode));
62 if (pNode == NULL)
63 {
64 result = false;
65 ALOGE("Failed to malloc");
66 goto clean_and_return;
67 }
68 TRACE("Allocated node: %8p (%8p)", pNode, pData);
69 pNode->pData = pData;
70 pNode->pNext = NULL;
71
72 pthread_mutex_lock(&pList->mutex);
73
74 /* Add the node to the list */
75 if (pList->pFirst == NULL)
76 {
77 /* Set the node as the head */
78 pList->pFirst = pNode;
79 }
80 else
81 {
82 /* Seek to the end of the list */
83 pLastNode = pList->pFirst;
84 while(pLastNode->pNext != NULL)
85 {
86 pLastNode = pLastNode->pNext;
87 }
88
89 /* Add the node to the current list */
90 pLastNode->pNext = pNode;
91 }
92
93 result = true;
94
95 clean_and_return:
96 pthread_mutex_unlock(&pList->mutex);
97 return result;
98 }
99
listRemove(listHead * pList,void * pData)100 bool listRemove(listHead* pList, void* pData)
101 {
102 struct listNode* pNode;
103 struct listNode* pRemovedNode;
104 bool result;
105
106 pthread_mutex_lock(&pList->mutex);
107
108 if (pList->pFirst == NULL)
109 {
110 /* Empty list */
111 ALOGE("Failed to deallocate (list empty)");
112 result = false;
113 goto clean_and_return;
114 }
115
116 pNode = pList->pFirst;
117 if (pList->pFirst->pData == pData)
118 {
119 /* Get the removed node */
120 pRemovedNode = pNode;
121
122 /* Remove the first node */
123 pList->pFirst = pList->pFirst->pNext;
124 }
125 else
126 {
127 while (pNode->pNext != NULL)
128 {
129 if (pNode->pNext->pData == pData)
130 {
131 /* Node found ! */
132 break;
133 }
134 pNode = pNode->pNext;
135 }
136
137 if (pNode->pNext == NULL)
138 {
139 /* Node not found */
140 result = false;
141 ALOGE("Failed to deallocate (not found %8p)", pData);
142 goto clean_and_return;
143 }
144
145 /* Get the removed node */
146 pRemovedNode = pNode->pNext;
147
148 /* Remove the node from the list */
149 pNode->pNext = pNode->pNext->pNext;
150 }
151
152 /* Deallocate the node */
153 TRACE("Deallocating node: %8p (%8p)", pRemovedNode, pRemovedNode->pData);
154 free(pRemovedNode);
155
156 result = true;
157
158 clean_and_return:
159 pthread_mutex_unlock(&pList->mutex);
160 return result;
161 }
162
listGetAndRemoveNext(listHead * pList,void ** ppData)163 bool listGetAndRemoveNext(listHead* pList, void** ppData)
164 {
165 struct listNode* pNode;
166 bool result;
167
168 pthread_mutex_lock(&pList->mutex);
169
170 if (pList->pFirst)
171 {
172 /* Empty list */
173 ALOGE("Failed to deallocate (list empty)");
174 result = false;
175 goto clean_and_return;
176 }
177
178 /* Work on the first node */
179 pNode = pList->pFirst;
180
181 /* Return the data */
182 if (ppData != NULL)
183 {
184 *ppData = pNode->pData;
185 }
186
187 /* Remove and deallocate the node */
188 pList->pFirst = pNode->pNext;
189 TRACE("Deallocating node: %8p (%8p)", pNode, pNode->pData);
190 free(pNode);
191
192 result = true;
193
194 clean_and_return:
195 listDump(pList);
196 pthread_mutex_unlock(&pList->mutex);
197 return result;
198 }
199
listDump(listHead * pList)200 void listDump(listHead* pList)
201 {
202 struct listNode* pNode = pList->pFirst;
203
204 TRACE("Node dump:");
205 while (pNode != NULL)
206 {
207 TRACE("- %8p (%8p)", pNode, pNode->pData);
208 pNode = pNode->pNext;
209 }
210 }
211