зеркало из https://github.com/mozilla/gecko-dev.git
281 строка
6.3 KiB
C
281 строка
6.3 KiB
C
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (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.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
#include "slist.h"
|
|
|
|
|
|
SSMSortedList *
|
|
SSMSortedList_New(SSMSortedListFn * functions)
|
|
{
|
|
SSMSortedList * list = NULL;
|
|
|
|
if (!functions)
|
|
goto loser;
|
|
|
|
list = PR_NEWZAP(SSMSortedList);
|
|
if (list == NULL)
|
|
goto loser;
|
|
|
|
list->lock = PR_NewMonitor();
|
|
if (list->lock == NULL)
|
|
goto loser;
|
|
|
|
list->func.keyCompare = functions->keyCompare;
|
|
list->func.freeListItemData = functions->freeListItemData;
|
|
list->func.freeListItemKey = functions->freeListItemKey;
|
|
|
|
PR_INIT_CLIST(&list->list);
|
|
list->nItems = 0;
|
|
return list;
|
|
loser:
|
|
if (list) {
|
|
if (list->lock)
|
|
PR_DestroyMonitor(list->lock);
|
|
PR_Free(list);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMSortedList_Destroy(SSMSortedList *victim)
|
|
{
|
|
PRCList * link, *next;
|
|
|
|
if (!victim)
|
|
goto done;
|
|
|
|
PR_EnterMonitor(victim->lock);
|
|
/* free elements */
|
|
for(link = PR_LIST_HEAD(&victim->list); link != &victim->list;){
|
|
next = PR_NEXT_LINK(link);
|
|
slist_remove_item(victim, (SSMSortedListItem *)link, PR_TRUE);
|
|
link = next;
|
|
}
|
|
|
|
PR_ExitMonitor(victim->lock);
|
|
PR_ASSERT(victim->nItems == 0);
|
|
PR_DestroyMonitor(victim->lock);
|
|
PR_Free(victim);
|
|
done:
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
SSMSortedListItem * slist_remove_item(SSMSortedList * list,
|
|
SSMSortedListItem * item,
|
|
PRBool doFree)
|
|
{
|
|
PR_REMOVE_LINK(&item->link);
|
|
list->nItems--;
|
|
if (doFree) {
|
|
list->func.freeListItemData(item->data);
|
|
list->func.freeListItemKey(item->key);
|
|
PR_Free(item);
|
|
return NULL;
|
|
}
|
|
else return item;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMSortedList_Insert(SSMSortedList * slist, void * key, void * data)
|
|
{
|
|
SSMSortedListItem * item, * nextItem;
|
|
|
|
if (!slist)
|
|
goto loser;
|
|
|
|
item = slist_allocate_item(key, data);
|
|
if (!item)
|
|
goto loser;
|
|
|
|
PR_EnterMonitor(slist->lock);
|
|
nextItem = slist_find_next(slist, key);
|
|
PR_INSERT_BEFORE(&item->link, &nextItem->link);
|
|
slist->nItems++;
|
|
PR_ExitMonitor(slist->lock);
|
|
|
|
return SSM_SUCCESS;
|
|
loser:
|
|
return SSM_FAILURE;
|
|
}
|
|
|
|
SSMSortedListItem * slist_allocate_item(void * key, void * data)
|
|
{
|
|
SSMSortedListItem * item;
|
|
|
|
item = PR_NEWZAP(SSMSortedListItem);
|
|
if (item)
|
|
{
|
|
item->data = data;
|
|
item->key = key;
|
|
}
|
|
return item;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMSortedList_Find(SSMSortedList * slist, void * key, void ** data)
|
|
{
|
|
SSMStatus rv = SSM_FAILURE;
|
|
SSMSortedListItem * item;
|
|
|
|
if (!slist || !data)
|
|
goto loser;
|
|
|
|
*data = NULL;
|
|
PR_EnterMonitor(slist->lock);
|
|
item = slist_find_item(slist, key);
|
|
if (item) {
|
|
*data = item->data;
|
|
rv = SSM_SUCCESS;
|
|
}
|
|
PR_ExitMonitor(slist->lock);
|
|
loser:
|
|
return rv;
|
|
}
|
|
|
|
SSMStatus
|
|
SSMSortedList_Remove(SSMSortedList * slist, void * key, void ** data)
|
|
{
|
|
SSMSortedListItem * item;
|
|
SSMStatus rv = SSM_FAILURE;
|
|
|
|
if (!slist)
|
|
goto loser;
|
|
PR_EnterMonitor(slist->lock);
|
|
item = slist_find_item(slist, key);
|
|
if (item) {
|
|
rv = SSM_SUCCESS;
|
|
if (data)
|
|
*data = item->data;
|
|
slist_remove_item(slist, item, PR_FALSE);
|
|
slist->func.freeListItemKey(item->key);
|
|
PR_Free(item);
|
|
}
|
|
PR_ExitMonitor(slist->lock);
|
|
loser:
|
|
return rv;
|
|
|
|
}
|
|
|
|
SSMStatus
|
|
SSMSortedList_FindNext(SSMSortedList * slist, void * key, void ** data)
|
|
{
|
|
SSMSortedListItem * item;
|
|
|
|
if (!slist || !data)
|
|
return SSM_FAILURE;
|
|
|
|
PR_EnterMonitor(slist->lock);
|
|
item = slist_find_next(slist, key);
|
|
*data = item->data;
|
|
PR_ExitMonitor(slist->lock);
|
|
return SSM_SUCCESS;
|
|
}
|
|
|
|
|
|
SSMSortedListItem *
|
|
slist_find_next(SSMSortedList * slist, void * key)
|
|
{
|
|
PRCList * link;
|
|
SSMSortedListItem * item;
|
|
|
|
for(link = PR_LIST_HEAD(&slist->list); link != &slist->list;
|
|
link = PR_NEXT_LINK(link))
|
|
if (slist->func.keyCompare(((SSMSortedListItem *)link)->key, key) > 0) {
|
|
/* insert here */
|
|
item = (SSMSortedListItem *)link;
|
|
goto done;
|
|
}
|
|
item = (SSMSortedListItem *)&slist->list;
|
|
done:
|
|
return item;
|
|
}
|
|
|
|
PRBool
|
|
SSMSortedList_Lookup(SSMSortedList * slist, void * key)
|
|
{
|
|
SSMSortedListItem * item;
|
|
if (!slist)
|
|
goto loser;
|
|
PR_EnterMonitor(slist->lock);
|
|
item = slist_find_item(slist, key);
|
|
PR_ExitMonitor(slist->lock);
|
|
if (item)
|
|
return PR_TRUE;
|
|
loser:
|
|
return PR_FALSE;
|
|
}
|
|
|
|
SSMSortedListItem *
|
|
slist_find_item(SSMSortedList * slist, void * key)
|
|
{
|
|
PRCList * link;
|
|
|
|
for(link = PR_LIST_HEAD(&slist->list); link != &slist->list;
|
|
link = PR_NEXT_LINK(link))
|
|
if (slist->func.keyCompare(((SSMSortedListItem *)link)->key, key) == 0) /* found it */
|
|
return ((SSMSortedListItem *)link);
|
|
return NULL;
|
|
}
|
|
|
|
PRIntn
|
|
SSMSortedList_Enumerate(SSMSortedList * slist, SSMSortedListEnumerator_fn func,
|
|
void * arg)
|
|
{
|
|
PRCList * link;
|
|
PRIntn numentries = 0;
|
|
SSMStatus rv;
|
|
|
|
if (!slist || !func)
|
|
goto loser;
|
|
|
|
PR_EnterMonitor(slist->lock);
|
|
for(link = PR_LIST_HEAD(&slist->list); link != &slist->list;
|
|
link = PR_NEXT_LINK(link)) {
|
|
rv = func(numentries, arg, ((SSMSortedListItem *)link)->key,
|
|
((SSMSortedListItem *)link)->data);
|
|
if (rv == SSM_SUCCESS)
|
|
numentries ++;
|
|
}
|
|
PR_ExitMonitor(slist->lock);
|
|
|
|
loser:
|
|
return numentries;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|