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