• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #ifdef HITLS_BSL_LIST
18 
19 #include "bsl_list_internal.h"
20 #include "bsl_err_internal.h"
21 #include "bsl_sal.h"
22 #include "securec.h"
23 #include "bsl_list.h"
24 
25 #define MAX_LIST_ELEM_CNT_DEFAULT 10000000
26 
27 /* this global var limits the maximum node number of a list */
28 static int32_t g_maxListCount = MAX_LIST_ELEM_CNT_DEFAULT;
29 
BslListAddAfterCurr(BslList * pList,void * pData)30 static uint32_t BslListAddAfterCurr(BslList *pList, void *pData)
31 {
32     BslListNode *newNode = NULL;
33 
34     /* check for missing argument */
35     if (pList == NULL) {
36         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
37         return BSL_NULL_INPUT;
38     }
39 
40     /* check if current is null */
41     if (pList->curr == NULL) {
42         BSL_ERR_PUSH_ERROR(BSL_LIST_INVALID_LIST_CURRENT);
43         return BSL_LIST_INVALID_LIST_CURRENT;
44     }
45 
46     /* allocate memory for new node */
47     newNode = BSL_SAL_Calloc(1, sizeof(BslListNode));
48     if (newNode == NULL) {
49         BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
50         return BSL_MALLOC_FAIL;
51     }
52 
53     newNode->data = pData;
54 
55     /* add new node after current */
56     newNode->next = pList->curr->next;
57     newNode->prev = pList->curr;
58     if ((pList->curr->next) != NULL) {
59         pList->curr->next->prev = newNode;
60     } else {
61         pList->last = newNode;
62     }
63 
64     pList->curr->next = newNode;
65 
66     pList->curr = newNode;
67     pList->count++;
68     return BSL_SUCCESS;
69 }
70 
BslListInsertBeforeCurr(BslList * pList,void * pData)71 static uint32_t BslListInsertBeforeCurr(BslList *pList, void *pData)
72 {
73     BslListNode *pNewNode = NULL;
74 
75     /* check if current is null */
76     /* check for missing argument */
77     if (pList == NULL) {
78         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
79         return BSL_NULL_INPUT;
80     }
81 
82     if (pList->curr == NULL) {
83         BSL_ERR_PUSH_ERROR(BSL_LIST_INVALID_LIST_CURRENT);
84         return BSL_LIST_INVALID_LIST_CURRENT;
85     }
86 
87     /* allocate memory for new node */
88     pNewNode = BSL_SAL_Calloc(1, sizeof(BslListNode));
89     if (pNewNode == NULL) {
90         BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
91         return BSL_MALLOC_FAIL;
92     }
93 
94     pNewNode->data = pData;
95 
96     /* add new node before current */
97     pNewNode->next = pList->curr;
98     pNewNode->prev = pList->curr->prev;
99     if ((pList->curr->prev) != NULL) {
100         pList->curr->prev->next = pNewNode;
101     } else {
102         pList->first = pNewNode;
103     }
104 
105     pList->curr->prev = pNewNode;
106 
107     pList->curr = pNewNode;
108     pList->count++;
109     return BSL_SUCCESS;
110 }
111 
BSL_LIST_AddElementInt(BslList * pList,void * pData,BslListPosition enPosition)112 uint32_t BSL_LIST_AddElementInt(BslList *pList, void *pData, BslListPosition enPosition)
113 {
114     BslListNode *pNewNode = NULL;
115 
116     if (pList->count >= g_maxListCount) {
117         BSL_ERR_PUSH_ERROR(BSL_LIST_FULL);
118         return BSL_LIST_FULL;
119     }
120 
121     if (pList->curr == NULL) {
122         if (pList->first == NULL) {
123             /* allocate memory for new node */
124             pNewNode = BSL_SAL_Calloc(1, sizeof(BslListNode));
125             if (pNewNode == NULL) {
126                 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
127                 return BSL_MALLOC_FAIL;
128             }
129 
130             pNewNode->data = pData;
131 
132             /* set the new node as the first and last node of list */
133             pNewNode->next = NULL;
134             pNewNode->prev = NULL;
135             pList->first = pNewNode;
136             pList->last = pNewNode;
137             pList->curr = pNewNode;
138             pList->count++;
139             return BSL_SUCCESS;
140         } else {
141             if (enPosition == BSL_LIST_POS_AFTER) {
142                 pList->curr = pList->last;
143             } else if (enPosition == BSL_LIST_POS_BEFORE) {
144                 pList->curr = pList->first;
145             }
146         }
147     }
148 
149     if ((enPosition == BSL_LIST_POS_AFTER) || (enPosition == BSL_LIST_POS_END)) {
150         if (enPosition == BSL_LIST_POS_END) {
151             pList->curr = pList->last;
152         }
153 
154         return BslListAddAfterCurr(pList, pData);
155     } else {
156         if (enPosition == BSL_LIST_POS_BEGIN) {
157             pList->curr = pList->first;
158         }
159 
160         return BslListInsertBeforeCurr(pList, pData);
161     }
162 }
163 
BSL_LIST_AddElement(BslList * pList,void * pData,BslListPosition enPosition)164 int32_t BSL_LIST_AddElement(BslList *pList, void *pData, BslListPosition enPosition)
165 {
166     /* check for missing argument */
167     if (pList == NULL) {
168         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
169         return BSL_INVALID_ARG;
170     }
171 
172     /* we are doing a range checking. the same thing is done in another way for clarity */
173     if (enPosition < BSL_LIST_POS_BEFORE || enPosition > BSL_LIST_POS_END) {
174         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
175         return BSL_INVALID_ARG;
176     }
177 
178     if (pData == NULL) {
179         BSL_ERR_PUSH_ERROR(BSL_LIST_DATA_NOT_AVAILABLE);
180         return BSL_LIST_DATA_NOT_AVAILABLE;
181     }
182 
183     return (int32_t)BSL_LIST_AddElementInt(pList, pData, enPosition);
184 }
185 
BSL_LIST_SetMaxElements(int32_t iMaxElements)186 int32_t BSL_LIST_SetMaxElements(int32_t iMaxElements)
187 {
188     if (iMaxElements < 0xffff || iMaxElements > 0xfffffff) {
189         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
190         return BSL_INVALID_ARG;
191     }
192 
193     g_maxListCount = iMaxElements;
194     return BSL_SUCCESS;
195 }
196 
BSL_LIST_GetMaxElements(void)197 int32_t BSL_LIST_GetMaxElements(void)
198 {
199     return g_maxListCount;
200 }
201 
BSL_LIST_DeleteAll(BslList * pList,BSL_LIST_PFUNC_FREE pfFreeFunc)202 void BSL_LIST_DeleteAll(BslList *pList, BSL_LIST_PFUNC_FREE pfFreeFunc)
203 {
204     BslListNode *pNode = NULL;
205     BslListNode *pNext = NULL;
206 
207     /* check for missing argument */
208     if (pList == NULL) {
209         return;
210     }
211 
212     pNode = pList->first;
213 
214     /* delete each node one by one */
215     while (pNode != NULL) {
216         pNext = pNode->next;
217         if (pfFreeFunc == NULL) {
218             BSL_SAL_FREE(pNode->data);
219         } else {
220             pfFreeFunc(pNode->data);
221             pNode->data = NULL;
222         }
223 
224         BSL_SAL_FREE(pNode);
225         pNode = pNext;
226         pList->count--;
227     }
228 
229     pList->first = pList->last = pList->curr = NULL;
230 }
231 
BSL_LIST_DeleteCurrent(BslList * pList,BSL_LIST_PFUNC_FREE pfFreeFunc)232 void BSL_LIST_DeleteCurrent(BslList *pList, BSL_LIST_PFUNC_FREE pfFreeFunc)
233 {
234     BslListNode *pNode = NULL;
235 
236     /* check for missing argument */
237     if (pList == NULL) {
238         return;
239     }
240 
241     if (pList->curr != NULL) {
242         /* delete current and set prev and next appropriately */
243         if (pList->curr->next != NULL) {
244             pList->curr->next->prev = pList->curr->prev;
245         } else {
246             pList->last = pList->curr->prev;
247         }
248 
249         if (pList->curr->prev != NULL) {
250             pList->curr->prev->next = pList->curr->next;
251         } else {
252             pList->first = pList->curr->next;
253         }
254 
255         pNode = pList->curr;
256 
257         pList->curr = pList->curr->next;
258         pList->count--;
259 
260         if (pfFreeFunc == NULL) {
261             BSL_SAL_FREE(pNode->data);
262         } else {
263             pfFreeFunc(pNode->data);
264         }
265 
266         BSL_SAL_FREE(pNode);
267     }
268 }
269 
BSL_LIST_DetachCurrent(BslList * pList)270 void BSL_LIST_DetachCurrent(BslList *pList)
271 {
272     /* check for missing argument */
273     BslListNode *tmpCurr = NULL;
274     if (pList == NULL) {
275         return;
276     }
277 
278     tmpCurr = pList->curr; // get the current node
279 
280     if (tmpCurr != NULL) {
281         /* delete current and set prev and next appropriately */
282         if (tmpCurr->next != NULL) { // check for last node
283             // current node is not the last node
284             tmpCurr->next->prev = tmpCurr->prev;
285 
286             // update the current node and point it to the next node
287             pList->curr = tmpCurr->next;
288         } else {
289             // current node is the last node
290             pList->last = tmpCurr->prev;
291 
292             // update the current node and point it to the last node
293             pList->curr = pList->last;
294         }
295 
296         if (tmpCurr->prev != NULL) { // check for the first node
297             // current node is not the first node
298             tmpCurr->prev->next = tmpCurr->next;
299         } else {
300             // current node is the first node
301             pList->first = tmpCurr->next;
302         }
303 
304         // we have already updated the pList->curr pointer appropriately
305         pList->count--;
306 
307         // now we must free the temp current node
308         BSL_SAL_FREE(tmpCurr);
309     }
310 }
311 
312 /**
313  * @ingroup bsl_list
314  * @brief Searches for an element and as well return immediately after internal error
315  *
316  * @param pList [IN] List in which object is searched for.
317  * @param pSearchFor [IN] Object to be searched for.
318  * @param pSearcher [IN] Search Function to be used.
319  * @param pstErr [OUT] Update the Internal Error if Any. If pstErr is not equal to NULL. If NULL this will be ignored.
320  * @retval void *
321  */
BSL_ListSearchInt(BslList * pList,const void * pSearchFor,BSL_LIST_PFUNC_CMP pSearcher,int32_t * pstErr)322 static void *BSL_ListSearchInt(BslList *pList, const void *pSearchFor, BSL_LIST_PFUNC_CMP pSearcher, int32_t *pstErr)
323 {
324     /* temporarily stores current node */
325     BslListNode *pstTempCurr = NULL;
326 
327     /* check for missing argument */
328     if (pList == NULL || pSearchFor == NULL) {
329         return NULL;
330     }
331 
332     pstTempCurr = pList->curr;
333 
334     /* parse all nodes one by one */
335     for ((pList)->curr = (pList)->first; (pList)->curr != NULL; (pList)->curr = (pList)->curr->next) {
336         if (pSearcher == NULL) {
337             /* if pSearcher is NULL, use memcmp */
338             if (memcmp(pList->curr->data, pSearchFor, (uint32_t)pList->dataSize) == 0) {
339                 return pList->curr->data;
340             }
341         } else {
342             int32_t retVal = pSearcher(pList->curr->data, pSearchFor);
343             if (retVal == SEC_INT_ERROR && pstErr != NULL) {
344                 *pstErr = SEC_INT_ERROR;
345                 return NULL;
346             }
347 
348             if (retVal == 0) {
349                 return pList->curr->data;
350             }
351         }
352     }
353 
354     /* no match found */
355     pList->curr = pstTempCurr;
356 
357     return NULL;
358 }
359 
BSL_LIST_Search(BslList * pList,const void * pSearchFor,BSL_LIST_PFUNC_CMP pSearcher,int32_t * pstErr)360 void *BSL_LIST_Search(BslList *pList, const void *pSearchFor, BSL_LIST_PFUNC_CMP pSearcher, int32_t *pstErr)
361 {
362     return BSL_ListSearchInt(pList, pSearchFor, pSearcher, pstErr);
363 }
364 
BSL_LIST_SearchEx(BslList * pList,const void * pSearchFor,BSL_LIST_PFUNC_CMP pSearcher)365 void *BSL_LIST_SearchEx(BslList *pList, const void *pSearchFor, BSL_LIST_PFUNC_CMP pSearcher)
366 {
367     return BSL_ListSearchInt(pList, pSearchFor, pSearcher, NULL);
368 }
369 
BSL_LIST_GetIndexNode(uint32_t ulIndex,BslList * pList)370 void *BSL_LIST_GetIndexNode(uint32_t ulIndex, BslList *pList)
371 {
372     if (pList == NULL) {
373         return NULL;
374     }
375 
376     if (ulIndex >= (uint32_t)pList->count) {
377         return NULL;
378     }
379 
380     if (BSL_LIST_GET_FIRST(pList) == NULL) {
381         return NULL;
382     }
383 
384     for (uint32_t ulIter = 0; ulIter < ulIndex; ulIter++) {
385         if (BSL_LIST_GET_NEXT(pList) == NULL) {
386             return NULL;
387         }
388     }
389 
390     return pList->curr->data;
391 }
392 
BSL_LIST_Copy(BslList * pSrcList,BSL_LIST_PFUNC_DUP pFuncCpy,BSL_LIST_PFUNC_FREE pfFreeFunc)393 BslList *BSL_LIST_Copy(BslList *pSrcList, BSL_LIST_PFUNC_DUP pFuncCpy, BSL_LIST_PFUNC_FREE pfFreeFunc)
394 {
395     void *pDstData = NULL;
396 
397     if (pSrcList == NULL) {
398         return NULL;
399     }
400 
401     /* we will first get the source data and if successful go ahead */
402     void *pSrcData = BSL_LIST_GET_FIRST(pSrcList);
403     if (pSrcData == NULL) {
404         return NULL;
405     }
406 
407     BslList *pDstList = BSL_LIST_New(pSrcList->dataSize);
408     if (pDstList == NULL) {
409         return NULL;
410     }
411 
412     for (int32_t i = 1; pSrcData != NULL && i <= BSL_LIST_COUNT(pSrcList); i++) {
413         if (pFuncCpy != NULL) {
414             pDstData = pFuncCpy(pSrcData);
415         } else {
416             uint32_t dataLen = (uint32_t)(pSrcList->dataSize);
417             pDstData = BSL_SAL_Calloc(1, dataLen);
418             /* we must do NULL check */
419             if (pDstData == NULL) {
420                 BSL_LIST_FREE(pDstList, pfFreeFunc);
421                 return NULL;
422             }
423 
424             (void)memcpy_s(pDstData, dataLen, pSrcData, dataLen);
425         }
426 
427         if (pDstData == NULL) {
428             BSL_LIST_FREE(pDstList, pfFreeFunc);
429             return NULL;
430         }
431 
432         if (BSL_LIST_AddElement(pDstList, pDstData, BSL_LIST_POS_AFTER) != BSL_SUCCESS) {
433             if (pfFreeFunc != NULL) {
434                 pfFreeFunc(pDstData);
435                 pDstData = NULL;
436             } else {
437                 BSL_SAL_FREE(pDstData);
438             }
439 
440             BSL_LIST_FREE(pDstList, pfFreeFunc);
441             return NULL;
442         }
443 
444         pSrcData = BSL_LIST_GET_NEXT(pSrcList);
445     }
446 
447     return pDstList;
448 }
449 
BSL_LIST_DeleteAllAfterSort(BslList * pList)450 void BSL_LIST_DeleteAllAfterSort(BslList *pList)
451 {
452     BslListNode *pNode = NULL;
453     BslListNode *pNext = NULL;
454 
455     /* check for missing argument */
456     if (pList == NULL) {
457         return;
458     }
459 
460     pNode = pList->first;
461 
462     /* delete each node one by one */
463     while (pNode != NULL) {
464         pNext = pNode->next;
465         BSL_SAL_FREE(pNode);
466         pNode = pNext;
467         pList->count--;
468     }
469 
470     pList->first = pList->last = pList->curr = NULL;
471 }
472 
BSL_LIST_Sort(BslList * pList,BSL_LIST_PFUNC_CMP pfCmp)473 BslList *BSL_LIST_Sort(BslList *pList, BSL_LIST_PFUNC_CMP pfCmp)
474 {
475     if (pfCmp == NULL) {
476         return NULL;
477     }
478 
479     int32_t iRet = BSL_ListSortInternal(pList, pfCmp);
480     if (iRet != BSL_SUCCESS) {
481         return NULL;
482     }
483 
484     return pList;
485 }
486 
BSL_LIST_FreeWithoutData(BslList * pstList)487 void BSL_LIST_FreeWithoutData(BslList *pstList)
488 {
489     BslListNode *node = NULL;
490     BslListNode *next = NULL;
491 
492     if (pstList != NULL) {
493         node = pstList->first;
494         while (node != NULL) {
495             next = node->next;
496             BSL_SAL_FREE(node);
497             node = next;
498         }
499 
500         BSL_SAL_FREE(pstList);
501     }
502 }
503 
BSL_LIST_RevList(BslList * pstList)504 void BSL_LIST_RevList(BslList *pstList)
505 {
506     struct BslListNode *pstTemp = NULL;
507 
508     if (pstList == NULL) {
509         return;
510     }
511 
512     pstList->curr = pstList->first;
513 
514     while (pstList->curr != NULL) {
515         pstTemp = pstList->curr->next;
516         pstList->curr->next = pstList->curr->prev;
517         pstList->curr->prev = pstTemp;
518         pstList->curr = pstTemp;
519     }
520 
521     pstList->curr = pstList->first;
522     pstList->first = pstList->last;
523     pstList->last = pstList->curr;
524     pstList->curr = pstList->first;
525 
526     return;
527 }
528 
BSL_ListConcatToEmptyList(BslList * pDestList,const BslList * pSrcList)529 BslList *BSL_ListConcatToEmptyList(BslList *pDestList, const BslList *pSrcList)
530 {
531     pDestList->count = pSrcList->count;
532     pDestList->first = pSrcList->first;
533     pDestList->last = pSrcList->last;
534     pDestList->curr = pDestList->first;
535 
536     return pDestList;
537 }
538 
BSL_ListConcatToNonEmptyList(BslList * pDestList,const BslList * pSrcList)539 BslList *BSL_ListConcatToNonEmptyList(BslList *pDestList, const BslList *pSrcList)
540 {
541     if ((pDestList->count + pSrcList->count) > g_maxListCount) {
542         return NULL;
543     }
544 
545     pDestList->count += pSrcList->count;
546     pSrcList->first->prev = pDestList->last;
547     pDestList->last->next = pSrcList->first;
548     pDestList->last = pSrcList->last;
549 
550     return pDestList;
551 }
552 
BSL_LIST_Concat(BslList * pDestList,const BslList * pSrcList)553 BslList *BSL_LIST_Concat(BslList *pDestList, const BslList *pSrcList)
554 {
555     if (pDestList == NULL || pSrcList == NULL) {
556         return NULL;
557     }
558 
559     if (pSrcList->count == 0) {
560         return pDestList;
561     }
562 
563     if (pDestList->count == 0) {
564         return BSL_ListConcatToEmptyList(pDestList, pSrcList);
565     }
566 
567     return BSL_ListConcatToNonEmptyList(pDestList, pSrcList);
568 }
569 #endif /* HITLS_BSL_LIST */
570