| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <com_android_nfc_list.h> |
| #include <com_android_nfc.h> |
| #include <pthread.h> |
| #include <errno.h> |
| #include <cutils/log.h> |
| |
| #undef LOG_TAG |
| #define LOG_TAG "NFC_LIST" |
| |
| bool listInit(listHead* pList) |
| { |
| pList->pFirst = NULL; |
| if(pthread_mutex_init(&pList->mutex, NULL) == -1) |
| { |
| LOGE("Mutex creation failed (errno=0x%08x)", errno); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool listDestroy(listHead* pList) |
| { |
| bool bListNotEmpty = true; |
| while (bListNotEmpty) { |
| bListNotEmpty = listGetAndRemoveNext(pList, NULL); |
| } |
| |
| if(pthread_mutex_destroy(&pList->mutex) == -1) |
| { |
| LOGE("Mutex destruction failed (errno=0x%08x)", errno); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool listAdd(listHead* pList, void* pData) |
| { |
| struct listNode* pNode; |
| struct listNode* pLastNode; |
| bool result; |
| |
| /* Create node */ |
| pNode = (struct listNode*)malloc(sizeof(listNode)); |
| if (pNode == NULL) |
| { |
| result = false; |
| LOGE("Failed to malloc"); |
| goto clean_and_return; |
| } |
| TRACE("Allocated node: %8p (%8p)", pNode, pData); |
| pNode->pData = pData; |
| pNode->pNext = NULL; |
| |
| pthread_mutex_lock(&pList->mutex); |
| |
| /* Add the node to the list */ |
| if (pList->pFirst == NULL) |
| { |
| /* Set the node as the head */ |
| pList->pFirst = pNode; |
| } |
| else |
| { |
| /* Seek to the end of the list */ |
| pLastNode = pList->pFirst; |
| while(pLastNode->pNext != NULL) |
| { |
| pLastNode = pLastNode->pNext; |
| } |
| |
| /* Add the node to the current list */ |
| pLastNode->pNext = pNode; |
| } |
| |
| result = true; |
| |
| clean_and_return: |
| pthread_mutex_unlock(&pList->mutex); |
| return result; |
| } |
| |
| bool listRemove(listHead* pList, void* pData) |
| { |
| struct listNode* pNode; |
| struct listNode* pRemovedNode; |
| bool result; |
| |
| pthread_mutex_lock(&pList->mutex); |
| |
| if (pList->pFirst == NULL) |
| { |
| /* Empty list */ |
| LOGE("Failed to deallocate (list empty)"); |
| result = false; |
| goto clean_and_return; |
| } |
| |
| pNode = pList->pFirst; |
| if (pList->pFirst->pData == pData) |
| { |
| /* Get the removed node */ |
| pRemovedNode = pNode; |
| |
| /* Remove the first node */ |
| pList->pFirst = pList->pFirst->pNext; |
| } |
| else |
| { |
| while (pNode->pNext != NULL) |
| { |
| if (pNode->pNext->pData == pData) |
| { |
| /* Node found ! */ |
| break; |
| } |
| pNode = pNode->pNext; |
| } |
| |
| if (pNode->pNext == NULL) |
| { |
| /* Node not found */ |
| result = false; |
| LOGE("Failed to deallocate (not found %8p)", pData); |
| goto clean_and_return; |
| } |
| |
| /* Get the removed node */ |
| pRemovedNode = pNode->pNext; |
| |
| /* Remove the node from the list */ |
| pNode->pNext = pNode->pNext->pNext; |
| } |
| |
| /* Deallocate the node */ |
| TRACE("Deallocating node: %8p (%8p)", pRemovedNode, pRemovedNode->pData); |
| free(pRemovedNode); |
| |
| result = true; |
| |
| clean_and_return: |
| pthread_mutex_unlock(&pList->mutex); |
| return result; |
| } |
| |
| bool listGetAndRemoveNext(listHead* pList, void** ppData) |
| { |
| struct listNode* pNode; |
| bool result; |
| |
| pthread_mutex_lock(&pList->mutex); |
| |
| if (pList->pFirst) |
| { |
| /* Empty list */ |
| LOGE("Failed to deallocate (list empty)"); |
| result = false; |
| goto clean_and_return; |
| } |
| |
| /* Work on the first node */ |
| pNode = pList->pFirst; |
| |
| /* Return the data */ |
| if (ppData != NULL) |
| { |
| *ppData = pNode->pData; |
| } |
| |
| /* Remove and deallocate the node */ |
| pList->pFirst = pNode->pNext; |
| TRACE("Deallocating node: %8p (%8p)", pNode, pNode->pData); |
| free(pNode); |
| |
| result = true; |
| |
| clean_and_return: |
| listDump(pList); |
| pthread_mutex_unlock(&pList->mutex); |
| return result; |
| } |
| |
| void listDump(listHead* pList) |
| { |
| struct listNode* pNode = pList->pFirst; |
| |
| TRACE("Node dump:"); |
| while (pNode != NULL) |
| { |
| TRACE("- %8p (%8p)", pNode, pNode->pData); |
| pNode = pNode->pNext; |
| } |
| } |