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