* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "hitls_build.h"
#ifdef HITLS_BSL_HASH
#include <stdlib.h>
#include <stdint.h>
#include "list_base.h"
#include "bsl_errno.h"
#include "bsl_sal.h"
#include "bsl_hash_list.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct BslListNodeSt ListNode;
int32_t BSL_ListInit(BSL_List *list, const ListDupFreeFuncPair *dataFunc)
{
int32_t ret = (int32_t)BSL_INTERNAL_EXCEPTION;
if (list != NULL) {
ret = ListRawInit(&list->rawList, NULL);
if (dataFunc == NULL) {
list->dataFunc.dupFunc = NULL;
list->dataFunc.freeFunc = NULL;
} else {
list->dataFunc.dupFunc = dataFunc->dupFunc;
list->dataFunc.freeFunc = dataFunc->freeFunc;
}
}
return ret;
}
static int32_t ListRemoveNode(BSL_List *list, ListNode *node)
{
if (list->dataFunc.freeFunc != NULL) {
(list->dataFunc.freeFunc((void *)(node->userdata)));
}
int32_t ret = ListRawRemove(&list->rawList, &node->rawNode);
if (ret == BSL_SUCCESS) {
BSL_SAL_FREE(node);
}
return ret;
}
int32_t BSL_ListClear(BSL_List *list)
{
int32_t ret = (int32_t)BSL_INTERNAL_EXCEPTION;
ListNode *node = NULL;
const RawList *rawList = NULL;
const ListRawNode *head = NULL;
if (list != NULL) {
rawList = &list->rawList;
head = &rawList->head;
while (!ListRawEmpty(rawList)) {
node = BSL_CONTAINER_OF(head->next, ListNode, rawNode);
ret = ListRemoveNode(list, node);
if (ret != BSL_SUCCESS) {
break;
}
}
}
return ret;
}
int32_t BSL_ListDeinit(BSL_List *list)
{
int32_t ret = (int32_t)BSL_INTERNAL_EXCEPTION;
if (list != NULL) {
ret = BSL_ListClear(list);
list->dataFunc.dupFunc = NULL;
list->dataFunc.freeFunc = NULL;
}
return ret;
}
static int32_t ListWriteUserdata(const BSL_List *list, ListNode *node, uintptr_t userData, size_t userDataSize)
{
if (list->dataFunc.dupFunc == NULL) {
node->userdata = userData;
return BSL_SUCCESS;
}
const void *copyBuff = list->dataFunc.dupFunc((void *)userData, userDataSize);
if (copyBuff == NULL) {
return BSL_INTERNAL_EXCEPTION;
}
node->userdata = (uintptr_t)copyBuff;
return BSL_SUCCESS;
}
static ListNode *NewNodeCreateByUserData(const BSL_List *list, uintptr_t userData, size_t userDataSize)
{
if (list == NULL) {
return NULL;
}
ListNode *node = (ListNode *)BSL_SAL_Malloc(sizeof(ListNode));
if (node != NULL) {
if (ListWriteUserdata(list, node, userData, userDataSize) != BSL_SUCCESS) {
BSL_SAL_Free(node);
node = NULL;
}
}
return node;
}
static int32_t ListPush(BSL_List *list, uintptr_t userData, size_t userDataSize, bool isFront)
{
ListNode *node = NewNodeCreateByUserData(list, userData, userDataSize);
if (node == NULL) {
return BSL_INTERNAL_EXCEPTION;
}
int32_t ret = isFront ? ListRawPushFront(&list->rawList, &node->rawNode) :
ListRawPushBack(&list->rawList, &node->rawNode);
if (ret != BSL_SUCCESS) {
if (list->dataFunc.freeFunc != NULL) {
list->dataFunc.freeFunc((void *)(node->userdata));
}
BSL_SAL_Free(node);
}
return ret;
}
int32_t BSL_ListPushFront(BSL_List *list, uintptr_t userData, size_t userDataSize)
{
return ListPush(list, userData, userDataSize, true);
}
int32_t BSL_ListPushBack(BSL_List *list, uintptr_t userData, size_t userDataSize)
{
return ListPush(list, userData, userDataSize, false);
}
int32_t BSL_ListInsert(BSL_List *list, const BSL_ListIterator it, uintptr_t userData, size_t userDataSize)
{
if (list == NULL || it == NULL) {
return BSL_INTERNAL_EXCEPTION;
}
ListNode *node = NewNodeCreateByUserData(list, userData, userDataSize);
if (node == NULL) {
return BSL_INTERNAL_EXCEPTION;
}
int32_t ret = ListRawInsert(&it->rawNode, &node->rawNode);
if (ret != BSL_SUCCESS) {
if (list->dataFunc.freeFunc != NULL) {
list->dataFunc.freeFunc((void *)(node->userdata));
}
BSL_SAL_Free(node);
}
return ret;
}
bool BSL_ListIsEmpty(const BSL_List *list)
{
return list == NULL ? true : ListRawEmpty(&list->rawList);
}
int32_t BSL_ListPopFront(BSL_List *list)
{
if (BSL_ListIsEmpty(list) == true) {
return BSL_INTERNAL_EXCEPTION;
}
ListNode *firstNode = BSL_CONTAINER_OF(list->rawList.head.next, ListNode, rawNode);
return ListRemoveNode(list, firstNode);
}
int32_t BSL_ListPopBack(BSL_List *list)
{
if (BSL_ListIsEmpty(list) == true) {
return BSL_INTERNAL_EXCEPTION;
}
ListNode *lastNode = BSL_CONTAINER_OF(list->rawList.head.prev, ListNode, rawNode);
return ListRemoveNode(list, lastNode);
}
BSL_ListIterator BSL_ListIterErase(BSL_List *list, BSL_ListIterator it)
{
if (BSL_ListIsEmpty(list) || (it == NULL) || (it == (BSL_ListIterator)(&list->rawList.head))) {
return NULL;
}
BSL_ListIterator retIt = BSL_CONTAINER_OF(it->rawNode.next, ListNode, rawNode);
return ListRemoveNode(list, it) == BSL_SUCCESS ? retIt : NULL;
}
uintptr_t BSL_ListFront(const BSL_List *list)
{
if (BSL_ListIsEmpty(list) == true) {
return (uintptr_t)0;
}
const ListNode *node = BSL_CONTAINER_OF(list->rawList.head.next, ListNode, rawNode);
return node->userdata;
}
uintptr_t BSL_ListBack(const BSL_List *list)
{
if (BSL_ListIsEmpty(list) == true) {
return (uintptr_t)0;
}
const ListNode *node = BSL_CONTAINER_OF(list->rawList.head.prev, ListNode, rawNode);
return node->userdata;
}
BSL_ListIterator BSL_ListIterBegin(const BSL_List *list)
{
return list == NULL ? NULL : BSL_CONTAINER_OF(list->rawList.head.next, ListNode, rawNode);
}
BSL_ListIterator BSL_ListIterEnd(BSL_List *list)
{
return list == NULL ? NULL : (BSL_ListIterator)(&list->rawList.head);
}
size_t BSL_ListSize(const BSL_List *list)
{
return list == NULL ? 0 : ListRawSize(&list->rawList);
}
BSL_ListIterator BSL_ListIterPrev(const BSL_List *list, const BSL_ListIterator it)
{
return (BSL_ListIsEmpty(list) == true || it == NULL) ? NULL : BSL_CONTAINER_OF(it->rawNode.prev, ListNode, rawNode);
}
BSL_ListIterator BSL_ListIterNext(const BSL_List *list, const BSL_ListIterator it)
{
return (BSL_ListIsEmpty(list) == true || it == NULL) ? NULL : BSL_CONTAINER_OF(it->rawNode.next, ListNode, rawNode);
}
uintptr_t BSL_ListIterData(const BSL_ListIterator it)
{
return it == NULL ? 0 : it->userdata;
}
BSL_ListIterator BSL_ListIterFind(BSL_List *list, ListKeyCmpFunc iterCmpFunc, uintptr_t data)
{
if (list == NULL || iterCmpFunc == NULL) {
return NULL;
}
BSL_ListIterator headIt = (BSL_ListIterator)BSL_CONTAINER_OF(&list->rawList.head, ListNode, rawNode);
BSL_ListIterator it = BSL_CONTAINER_OF(list->rawList.head.next, ListNode, rawNode);
while (it != headIt) {
if (iterCmpFunc(it->userdata, data) == 0) {
return it;
}
it = BSL_CONTAINER_OF(it->rawNode.next, ListNode, rawNode);
}
return NULL;
}
#ifdef __cplusplus
}
#endif
#endif