Index: mozilla/security/nss/lib/base/list.c |
=================================================================== |
--- mozilla/security/nss/lib/base/list.c (revision 191424) |
+++ mozilla/security/nss/lib/base/list.c (working copy) |
@@ -1,405 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-#ifdef DEBUG |
-static const char CVS_ID[] = "@(#) $RCSfile: list.c,v $ $Revision: 1.21 $ $Date: 2012/04/25 14:49:26 $"; |
-#endif /* DEBUG */ |
- |
-/* |
- * list.c |
- * |
- * This contains the implementation of NSS's thread-safe linked list. |
- */ |
- |
-#ifndef BASE_H |
-#include "base.h" |
-#endif /* BASE_H */ |
- |
-struct nssListElementStr { |
- PRCList link; |
- void *data; |
-}; |
- |
-typedef struct nssListElementStr nssListElement; |
- |
-struct nssListStr { |
- NSSArena *arena; |
- PZLock *lock; |
- nssListElement *head; |
- PRUint32 count; |
- nssListCompareFunc compareFunc; |
- nssListSortFunc sortFunc; |
- PRBool i_alloced_arena; |
-}; |
- |
-struct nssListIteratorStr { |
- PZLock *lock; |
- nssList *list; |
- nssListElement *current; |
-}; |
- |
-#define NSSLIST_LOCK_IF(list) \ |
- if ((list)->lock) PZ_Lock((list)->lock) |
- |
-#define NSSLIST_UNLOCK_IF(list) \ |
- if ((list)->lock) PZ_Unlock((list)->lock) |
- |
-static PRBool |
-pointer_compare(void *a, void *b) |
-{ |
- return (PRBool)(a == b); |
-} |
- |
-static nssListElement * |
-nsslist_get_matching_element(nssList *list, void *data) |
-{ |
- PRCList *link; |
- nssListElement *node; |
- node = list->head; |
- if (!node) { |
- return NULL; |
- } |
- link = &node->link; |
- while (node) { |
- /* using a callback slows things down when it's just compare ... */ |
- if (list->compareFunc(node->data, data)) { |
- break; |
- } |
- link = &node->link; |
- if (link == PR_LIST_TAIL(&list->head->link)) { |
- node = NULL; |
- break; |
- } |
- node = (nssListElement *)PR_NEXT_LINK(&node->link); |
- } |
- return node; |
-} |
- |
-NSS_IMPLEMENT nssList * |
-nssList_Create |
-( |
- NSSArena *arenaOpt, |
- PRBool threadSafe |
-) |
-{ |
- NSSArena *arena; |
- nssList *list; |
- PRBool i_alloced; |
- if (arenaOpt) { |
- arena = arenaOpt; |
- i_alloced = PR_FALSE; |
- } else { |
- arena = nssArena_Create(); |
- i_alloced = PR_TRUE; |
- } |
- if (!arena) { |
- return (nssList *)NULL; |
- } |
- list = nss_ZNEW(arena, nssList); |
- if (!list) { |
- if (!arenaOpt) { |
- NSSArena_Destroy(arena); |
- } |
- return (nssList *)NULL; |
- } |
- if (threadSafe) { |
- list->lock = PZ_NewLock(nssILockOther); |
- if (!list->lock) { |
- if (arenaOpt) { |
- nss_ZFreeIf(list); |
- } else { |
- NSSArena_Destroy(arena); |
- } |
- return (nssList *)NULL; |
- } |
- } |
- list->arena = arena; |
- list->i_alloced_arena = i_alloced; |
- list->compareFunc = pointer_compare; |
- return list; |
-} |
- |
-NSS_IMPLEMENT PRStatus |
-nssList_Destroy(nssList *list) |
-{ |
- if (!list->i_alloced_arena) { |
- nssList_Clear(list, NULL); |
- } |
- if (list->lock) { |
- (void)PZ_DestroyLock(list->lock); |
- } |
- if (list->i_alloced_arena) { |
- NSSArena_Destroy(list->arena); |
- list = NULL; |
- } |
- nss_ZFreeIf(list); |
- return PR_SUCCESS; |
-} |
- |
-NSS_IMPLEMENT void |
-nssList_SetCompareFunction(nssList *list, nssListCompareFunc compareFunc) |
-{ |
- list->compareFunc = compareFunc; |
-} |
- |
-NSS_IMPLEMENT void |
-nssList_SetSortFunction(nssList *list, nssListSortFunc sortFunc) |
-{ |
- /* XXX if list already has elements, sort them */ |
- list->sortFunc = sortFunc; |
-} |
- |
-NSS_IMPLEMENT nssListCompareFunc |
-nssList_GetCompareFunction(nssList *list) |
-{ |
- return list->compareFunc; |
-} |
- |
-NSS_IMPLEMENT void |
-nssList_Clear(nssList *list, nssListElementDestructorFunc destructor) |
-{ |
- PRCList *link; |
- nssListElement *node, *tmp; |
- NSSLIST_LOCK_IF(list); |
- node = list->head; |
- list->head = NULL; |
- while (node && list->count > 0) { |
- if (destructor) (*destructor)(node->data); |
- link = &node->link; |
- tmp = (nssListElement *)PR_NEXT_LINK(link); |
- PR_REMOVE_LINK(link); |
- nss_ZFreeIf(node); |
- node = tmp; |
- --list->count; |
- } |
- NSSLIST_UNLOCK_IF(list); |
-} |
- |
-static PRStatus |
-nsslist_add_element(nssList *list, void *data) |
-{ |
- nssListElement *node = nss_ZNEW(list->arena, nssListElement); |
- if (!node) { |
- return PR_FAILURE; |
- } |
- PR_INIT_CLIST(&node->link); |
- node->data = data; |
- if (list->head) { |
- if (list->sortFunc) { |
- PRCList *link; |
- nssListElement *currNode; |
- currNode = list->head; |
- /* insert in ordered list */ |
- while (currNode) { |
- link = &currNode->link; |
- if (list->sortFunc(data, currNode->data) <= 0) { |
- /* new element goes before current node */ |
- PR_INSERT_BEFORE(&node->link, link); |
- /* reset head if this is first */ |
- if (currNode == list->head) list->head = node; |
- break; |
- } |
- if (link == PR_LIST_TAIL(&list->head->link)) { |
- /* reached end of list, append */ |
- PR_INSERT_AFTER(&node->link, link); |
- break; |
- } |
- currNode = (nssListElement *)PR_NEXT_LINK(&currNode->link); |
- } |
- } else { |
- /* not sorting */ |
- PR_APPEND_LINK(&node->link, &list->head->link); |
- } |
- } else { |
- list->head = node; |
- } |
- ++list->count; |
- return PR_SUCCESS; |
-} |
- |
-NSS_IMPLEMENT PRStatus |
-nssList_Add(nssList *list, void *data) |
-{ |
- PRStatus nssrv; |
- NSSLIST_LOCK_IF(list); |
- nssrv = nsslist_add_element(list, data); |
- NSSLIST_UNLOCK_IF(list); |
- return PR_SUCCESS; |
-} |
- |
-NSS_IMPLEMENT PRStatus |
-nssList_AddUnique(nssList *list, void *data) |
-{ |
- PRStatus nssrv; |
- nssListElement *node; |
- NSSLIST_LOCK_IF(list); |
- node = nsslist_get_matching_element(list, data); |
- if (node) { |
- /* already in, finish */ |
- NSSLIST_UNLOCK_IF(list); |
- return PR_SUCCESS; |
- } |
- nssrv = nsslist_add_element(list, data); |
- NSSLIST_UNLOCK_IF(list); |
- return nssrv; |
-} |
- |
-NSS_IMPLEMENT PRStatus |
-nssList_Remove(nssList *list, void *data) |
-{ |
- nssListElement *node; |
- NSSLIST_LOCK_IF(list); |
- node = nsslist_get_matching_element(list, data); |
- if (node) { |
- if (node == list->head) { |
- list->head = (nssListElement *)PR_NEXT_LINK(&node->link); |
- } |
- PR_REMOVE_LINK(&node->link); |
- nss_ZFreeIf(node); |
- if (--list->count == 0) { |
- list->head = NULL; |
- } |
- } |
- NSSLIST_UNLOCK_IF(list); |
- return PR_SUCCESS; |
-} |
- |
-NSS_IMPLEMENT void * |
-nssList_Get(nssList *list, void *data) |
-{ |
- nssListElement *node; |
- NSSLIST_LOCK_IF(list); |
- node = nsslist_get_matching_element(list, data); |
- NSSLIST_UNLOCK_IF(list); |
- return (node) ? node->data : NULL; |
-} |
- |
-NSS_IMPLEMENT PRUint32 |
-nssList_Count(nssList *list) |
-{ |
- return list->count; |
-} |
- |
-NSS_IMPLEMENT PRStatus |
-nssList_GetArray(nssList *list, void **rvArray, PRUint32 maxElements) |
-{ |
- nssListElement *node; |
- PRUint32 i = 0; |
- PR_ASSERT(maxElements > 0); |
- node = list->head; |
- if (!node) { |
- return PR_SUCCESS; |
- } |
- NSSLIST_LOCK_IF(list); |
- while (node) { |
- rvArray[i++] = node->data; |
- if (i == maxElements) break; |
- node = (nssListElement *)PR_NEXT_LINK(&node->link); |
- if (node == list->head) { |
- break; |
- } |
- } |
- NSSLIST_UNLOCK_IF(list); |
- return PR_SUCCESS; |
-} |
- |
-NSS_IMPLEMENT nssList * |
-nssList_Clone(nssList *list) |
-{ |
- nssList *rvList; |
- nssListElement *node; |
- rvList = nssList_Create(NULL, (list->lock != NULL)); |
- if (!rvList) { |
- return NULL; |
- } |
- NSSLIST_LOCK_IF(list); |
- if (list->count > 0) { |
- node = list->head; |
- while (PR_TRUE) { |
- nssList_Add(rvList, node->data); |
- node = (nssListElement *)PR_NEXT_LINK(&node->link); |
- if (node == list->head) { |
- break; |
- } |
- } |
- } |
- NSSLIST_UNLOCK_IF(list); |
- return rvList; |
-} |
- |
-NSS_IMPLEMENT nssListIterator * |
-nssList_CreateIterator(nssList *list) |
-{ |
- nssListIterator *rvIterator; |
- rvIterator = nss_ZNEW(NULL, nssListIterator); |
- if (!rvIterator) { |
- return NULL; |
- } |
- rvIterator->list = nssList_Clone(list); |
- if (!rvIterator->list) { |
- nss_ZFreeIf(rvIterator); |
- return NULL; |
- } |
- rvIterator->current = rvIterator->list->head; |
- if (list->lock) { |
- rvIterator->lock = PZ_NewLock(nssILockOther); |
- if (!rvIterator->lock) { |
- nssList_Destroy(rvIterator->list); |
- nss_ZFreeIf(rvIterator); |
- rvIterator = NULL; |
- } |
- } |
- return rvIterator; |
-} |
- |
-NSS_IMPLEMENT void |
-nssListIterator_Destroy(nssListIterator *iter) |
-{ |
- if (iter->lock) { |
- (void)PZ_DestroyLock(iter->lock); |
- } |
- nssList_Destroy(iter->list); |
- nss_ZFreeIf(iter); |
-} |
- |
-NSS_IMPLEMENT void * |
-nssListIterator_Start(nssListIterator *iter) |
-{ |
- NSSLIST_LOCK_IF(iter); |
- if (iter->list->count == 0) { |
- return NULL; |
- } |
- iter->current = iter->list->head; |
- return iter->current->data; |
-} |
- |
-NSS_IMPLEMENT void * |
-nssListIterator_Next(nssListIterator *iter) |
-{ |
- nssListElement *node; |
- PRCList *link; |
- if (iter->list->count == 1 || iter->current == NULL) { |
- /* Reached the end of the list. Don't change the state, force to |
- * user to call nssList_Finish to clean up. |
- */ |
- return NULL; |
- } |
- node = (nssListElement *)PR_NEXT_LINK(&iter->current->link); |
- link = &node->link; |
- if (link == PR_LIST_TAIL(&iter->list->head->link)) { |
- /* Signal the end of the list. */ |
- iter->current = NULL; |
- return node->data; |
- } |
- iter->current = node; |
- return node->data; |
-} |
- |
-NSS_IMPLEMENT PRStatus |
-nssListIterator_Finish(nssListIterator *iter) |
-{ |
- iter->current = iter->list->head; |
- return (iter->lock) ? PZ_Unlock(iter->lock) : PR_SUCCESS; |
-} |
- |