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 <errno.h>
20 #include <malloc.h>
21 #include <pthread.h>
22 #include <cutils/log.h>
23
24 #undef LOG_TAG
25 #define LOG_TAG "NFC_LIST"
26
listInit(listHead * pList)27 bool listInit(listHead* pList)
28 {
29 pList->pFirst = NULL;
30 if(pthread_mutex_init(&pList->mutex, NULL) == -1)
31 {
32 ALOGE("Mutex creation failed (errno=0x%08x)", errno);
33 return false;
34 }
35
36 return true;
37 }
38
listDestroy(listHead * pList)39 bool listDestroy(listHead* pList)
40 {
41 bool bListNotEmpty = true;
42 while (bListNotEmpty) {
43 bListNotEmpty = listGetAndRemoveNext(pList, NULL);
44 }
45
46 if(pthread_mutex_destroy(&pList->mutex) == -1)
47 {
48 ALOGE("Mutex destruction failed (errno=0x%08x)", errno);
49 return false;
50 }
51
52 return true;
53 }
54
listAdd(listHead * pList,void * pData)55 bool listAdd(listHead* pList, void* pData)
56 {
57 struct listNode* pNode;
58 struct listNode* pLastNode;
59 bool result;
60
61 /* Create node */
62 pNode = (struct listNode*)malloc(sizeof(listNode));
63 if (pNode == NULL)
64 {
65 result = false;
66 ALOGE("Failed to malloc");
67 goto clean_and_return;
68 }
69 TRACE("Allocated node: %8p (%8p)", pNode, pData);
70 pNode->pData = pData;
71 pNode->pNext = NULL;
72
73 pthread_mutex_lock(&pList->mutex);
74
75 /* Add the node to the list */
76 if (pList->pFirst == NULL)
77 {
78 /* Set the node as the head */
79 pList->pFirst = pNode;
80 }
81 else
82 {
83 /* Seek to the end of the list */
84 pLastNode = pList->pFirst;
85 while(pLastNode->pNext != NULL)
86 {
87 pLastNode = pLastNode->pNext;
88 }
89
90 /* Add the node to the current list */
91 pLastNode->pNext = pNode;
92 }
93
94 result = true;
95
96 clean_and_return:
97 pthread_mutex_unlock(&pList->mutex);
98 return result;
99 }
100
listRemove(listHead * pList,void * pData)101 bool listRemove(listHead* pList, void* pData)
102 {
103 struct listNode* pNode;
104 struct listNode* pRemovedNode;
105 bool result;
106
107 pthread_mutex_lock(&pList->mutex);
108
109 if (pList->pFirst == NULL)
110 {
111 /* Empty list */
112 ALOGE("Failed to deallocate (list empty)");
113 result = false;
114 goto clean_and_return;
115 }
116
117 pNode = pList->pFirst;
118 if (pList->pFirst->pData == pData)
119 {
120 /* Get the removed node */
121 pRemovedNode = pNode;
122
123 /* Remove the first node */
124 pList->pFirst = pList->pFirst->pNext;
125 }
126 else
127 {
128 while (pNode->pNext != NULL)
129 {
130 if (pNode->pNext->pData == pData)
131 {
132 /* Node found ! */
133 break;
134 }
135 pNode = pNode->pNext;
136 }
137
138 if (pNode->pNext == NULL)
139 {
140 /* Node not found */
141 result = false;
142 ALOGE("Failed to deallocate (not found %8p)", pData);
143 goto clean_and_return;
144 }
145
146 /* Get the removed node */
147 pRemovedNode = pNode->pNext;
148
149 /* Remove the node from the list */
150 pNode->pNext = pNode->pNext->pNext;
151 }
152
153 /* Deallocate the node */
154 TRACE("Deallocating node: %8p (%8p)", pRemovedNode, pRemovedNode->pData);
155 free(pRemovedNode);
156
157 result = true;
158
159 clean_and_return:
160 pthread_mutex_unlock(&pList->mutex);
161 return result;
162 }
163
listGetAndRemoveNext(listHead * pList,void ** ppData)164 bool listGetAndRemoveNext(listHead* pList, void** ppData)
165 {
166 struct listNode* pNode;
167 bool result;
168
169 pthread_mutex_lock(&pList->mutex);
170
171 if (pList->pFirst)
172 {
173 /* Empty list */
174 ALOGE("Failed to deallocate (list empty)");
175 result = false;
176 goto clean_and_return;
177 }
178
179 /* Work on the first node */
180 pNode = pList->pFirst;
181
182 /* Return the data */
183 if (ppData != NULL)
184 {
185 *ppData = pNode->pData;
186 }
187
188 /* Remove and deallocate the node */
189 pList->pFirst = pNode->pNext;
190 TRACE("Deallocating node: %8p (%8p)", pNode, pNode->pData);
191 free(pNode);
192
193 result = true;
194
195 clean_and_return:
196 listDump(pList);
197 pthread_mutex_unlock(&pList->mutex);
198 return result;
199 }
200
listDump(listHead * pList)201 void listDump(listHead* pList)
202 {
203 struct listNode* pNode = pList->pFirst;
204
205 TRACE("Node dump:");
206 while (pNode != NULL)
207 {
208 TRACE("- %8p (%8p)", pNode, pNode->pData);
209 pNode = pNode->pNext;
210 }
211 }
212