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