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 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 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 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 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 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 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