1 /*
2  * Copyright (C) 2017-2018 NXP Semiconductors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18 ************************* Header Files ****************************************
19 */
20 
21 /* System include files */
22 
23 #include "phOsal_LinkList.h"
24 
25 #include <cstring>
26 
27 /**
28  * Structure for link list node
29  */
30 typedef struct phOsal_ListNode {
31   struct phOsal_ListNode* ps_next;
32   void* pvData;
33 } phOsal_ListNode_t;
34 
35 /**
36  * Context structure for Link List
37  */
38 typedef struct phOsal_ListCtxt {
39   phOsal_ListCreateParams_t sListCreateParams;
40   phOsal_ListNode_t* psHead;
41   phOsal_ListNode_t* psTail;
42   uint32_t dwNumNodes;
43 } phOsal_ListCtxt_t;
44 
45 #undef ALOGD
46 #define ALOGD
47 
48 static OSALSTATUS phOsali_ListDeleteAllNodes(void* pvListHandle);
49 
50 /**
51  * Create resources for linked list data structure
52  */
phOsal_ListCreate(void ** phListHandle,phOsal_ListCreateParams_t * psCreateParams)53 OSALSTATUS phOsal_ListCreate(void** phListHandle,
54                              phOsal_ListCreateParams_t* psCreateParams) {
55   phOsal_ListCtxt_t* psListCtxt = NULL;
56   void* memHdl;
57 
58   /*Input validity check*/
59   if (NULL == psCreateParams || NULL == phListHandle) {
60     return OSALSTATUS_INVALID_PARAMS;
61   } /*    if(NULL == psCreateParams || NULL == ph_ll_handle)*/
62 
63   /*Allocate memory to linked list context*/
64   memHdl = psCreateParams->memHdl;
65   psListCtxt = (phOsal_ListCtxt_t*)psCreateParams->MemAllocCb(
66       memHdl, sizeof(phOsal_ListCtxt_t));
67 
68   if (NULL == psListCtxt) {
69     return OSALSTATUS_FAILED;
70   } /*if(NULL == psListCtxt)*/
71 
72   memset(psListCtxt, 0, sizeof(phOsal_ListCtxt_t));
73 
74   /*Copy required variables from inargs to context*/
75   memcpy(&(psListCtxt->sListCreateParams), psCreateParams,
76          sizeof(phOsal_ListCreateParams_t));
77 
78   /*Initialize context variables*/
79   psListCtxt->psHead = NULL;
80   psListCtxt->psTail = NULL;
81   psListCtxt->dwNumNodes = 0;
82 
83   /*Update the link list handle*/
84   *phListHandle = psListCtxt;
85 
86   return OSALSTATUS_SUCCESS;
87 }
88 
89 /**
90  * Insert an object/node into linkedlist
91  */
phOsal_ListInsertNode(void * pvListHandle,PHOSAL_LIST_POSITION_T eListPos,void * pvData)92 OSALSTATUS phOsal_ListInsertNode(void* pvListHandle,
93                                  PHOSAL_LIST_POSITION_T eListPos,
94                                  void* pvData) {
95   phOsal_ListCtxt_t* psListCtxt = (phOsal_ListCtxt_t*)pvListHandle;
96   phOsal_ListNode_t* psNodeTba = NULL; /*Node to be added*/
97 
98   /*Validity check*/
99   if (NULL == pvListHandle) {
100     return OSALSTATUS_INVALID_PARAMS;
101   } /*if(NULL == pvListHandle)*/
102 
103   /*Create new obj node to be added and update its parameters*/
104   psNodeTba = (phOsal_ListNode_t*)psListCtxt->sListCreateParams.MemAllocCb(
105       psListCtxt->sListCreateParams.memHdl, sizeof(phOsal_ListNode_t));
106 
107   psNodeTba->ps_next = NULL;
108   psNodeTba->pvData = pvData;
109 
110   switch (eListPos) /*Update head and tail pointers based on the position of
111                     obj to be added*/
112   {
113     case PHOSAL_LIST_POS_TAIL: {
114       if (NULL == psListCtxt->psTail) {
115         /** First node is being added */
116         psListCtxt->psHead = psNodeTba;
117         psListCtxt->psTail = psNodeTba;
118       } else {
119         /** Node is being added to the tail of the list */
120         psListCtxt->psTail->ps_next = psNodeTba;
121         psListCtxt->psTail = psNodeTba;
122       } /*if (NULL == psListCtxt->psTail)*/
123 
124       break;
125     } /*case PHOSAL_LIST_POS_TAIL:*/
126     case PHOSAL_LIST_POS_HEAD: {
127       if (NULL == psListCtxt->psHead) {
128         /** First node is being added */
129         psListCtxt->psHead = psNodeTba;
130         psListCtxt->psTail = psNodeTba;
131       } else {
132         /** Node is being added to the head of the list */
133         psNodeTba->ps_next = psListCtxt->psHead;
134         psListCtxt->psHead = psNodeTba;
135       } /*if (NULL == psListCtxt->psHead)*/
136       break;
137     } /*case PHOSAL_LIST_POS_HEAD:*/
138     case PHOSAL_LIST_POS_CUR: {
139       return OSALSTATUS_NOT_SUPPORTED;
140       ; /*TBD: Currently not supported*/
141         // break;
142     }   /*case PHOSAL_LIST_POS_CUR:*/
143     case PHOSAL_LIST_POS_NEXT: {
144       return OSALSTATUS_NOT_SUPPORTED;
145       ; /*TBD: Currently not supported*/
146         // break;
147     }   /*case PHOSAL_LIST_POS_NEXT:*/
148     case PHOSAL_LIST_POS_PREV: {
149       return OSALSTATUS_NOT_SUPPORTED;
150       ; /*TBD: Currently not supported*/
151       break;
152     } /*case PHOSAL_LIST_POS_PREV:*/
153     default: {
154       return OSALSTATUS_INVALID_PARAMS;
155     } /*default*/
156   }   /*switch(eListPos)*/
157 
158   psListCtxt->dwNumNodes++;
159   return OSALSTATUS_SUCCESS;
160 }
161 
162 /**
163  * Removes an object/node from linkedlist
164  */
phOsal_ListRemoveNode(void * pvListHandle,PHOSAL_LIST_POSITION_T eListPos,void ** ppvData)165 OSALSTATUS phOsal_ListRemoveNode(void* pvListHandle,
166                                  PHOSAL_LIST_POSITION_T eListPos,
167                                  void** ppvData) {
168   phOsal_ListCtxt_t* psListCtxt = (phOsal_ListCtxt_t*)pvListHandle;
169   phOsal_ListNode_t* psNodeTbd = NULL; /*Node to be deleted*/
170 
171   /*Validity check*/
172   if (NULL == pvListHandle || NULL == ppvData) {
173     return OSALSTATUS_INVALID_PARAMS;
174   } /*if(NULL == pvListHandle || NULL == pvData)*/
175 
176   switch (eListPos) /*Update head and tail pointers based on the position of
177                     obj to be deleted*/
178   {
179     case PHOSAL_LIST_POS_HEAD: {
180       if (NULL == psListCtxt->psHead) { /** No elements in the list*/
181         *ppvData = NULL;
182         return OSALSTATUS_INVALID_PARAMS;
183       } else if (NULL ==
184                  psListCtxt->psHead
185                      ->ps_next) { /** There is only one object in the list*/
186         *ppvData = psListCtxt->psHead->pvData;
187         psNodeTbd = psListCtxt->psHead;
188         psListCtxt->psHead = NULL;
189         psListCtxt->psTail = NULL;
190       } else { /*There are more than one element in the list*/
191         *ppvData = psListCtxt->psHead->pvData;
192         psNodeTbd = psListCtxt->psHead;
193         psListCtxt->psHead = psListCtxt->psHead->ps_next;
194       } /*if (NULL == psListCtxt->psHead)*/
195 
196       break;
197     }
198     case PHOSAL_LIST_POS_TAIL: {
199       if (NULL == psListCtxt->psTail) { /** No elements in the list*/
200         *ppvData = NULL;
201         return OSALSTATUS_INVALID_PARAMS;
202       } else if (NULL ==
203                  psListCtxt->psHead
204                      ->ps_next) { /** There is only one object in the list*/
205 
206         *ppvData = psListCtxt->psHead->pvData;
207         psNodeTbd = psListCtxt->psHead;
208         psListCtxt->psHead = NULL;
209         psListCtxt->psTail = NULL;
210       } else { /*There are more than one element in the list*/
211         phOsal_ListNode_t* ps_ll_node = NULL;
212         phOsal_ListNode_t* ps_ll_node_prev = NULL;
213 
214         ps_ll_node = psListCtxt->psHead;
215 
216         /*Traverse till the end of the link list*/
217         while (NULL != ps_ll_node->ps_next) {
218           ps_ll_node_prev = ps_ll_node;
219           ps_ll_node = ps_ll_node->ps_next;
220         } /*while(NULL != ps_ll_node->ps_next)*/
221 
222         *ppvData = ps_ll_node->pvData;
223         psNodeTbd = ps_ll_node;
224         psListCtxt->psTail = ps_ll_node_prev;
225 
226       } /*if (NULL == psListCtxt->psTail)*/
227       break;
228     }
229     case PHOSAL_LIST_POS_CUR: {
230       return OSALSTATUS_NOT_SUPPORTED;
231       ; /*TBD: Currently not supported*/
232         // break;
233     }   /*case PHOSAL_LIST_POS_CUR:*/
234     case PHOSAL_LIST_POS_NEXT: {
235       return OSALSTATUS_NOT_SUPPORTED;
236       ; /*TBD: Currently not supported*/
237         // break;
238     }   /*case PHOSAL_LIST_POS_NEXT:*/
239     case PHOSAL_LIST_POS_PREV: {
240       return OSALSTATUS_NOT_SUPPORTED;
241       ; /*TBD: Currently not supported*/
242         // break;
243     }   /*case PHOSAL_LIST_POS_PREV:*/
244     default: {
245       return OSALSTATUS_INVALID_PARAMS;
246     } /*default:*/
247   }   /*switch(eListPos)*/
248 
249   { /*Free up the memory for the node to be deleted*/
250 
251     psListCtxt->sListCreateParams.MemFreeCb(
252         psListCtxt->sListCreateParams.memHdl, psNodeTbd);
253 
254     psListCtxt->dwNumNodes--;
255   }
256   return OSALSTATUS_SUCCESS;
257 }
258 
259 /**
260  * Destroy the  linkedlist
261  */
phOsal_ListDestroy(void * pvListHandle)262 OSALSTATUS phOsal_ListDestroy(void* pvListHandle) {
263   phOsal_ListCtxt_t* psListCtxt = (phOsal_ListCtxt_t*)pvListHandle;
264 
265   /*Validity check*/
266   if (NULL == pvListHandle) {
267     return OSALSTATUS_INVALID_PARAMS;
268   } /*if(NULL == pvListHandle)*/
269 
270   /*Delete all nodes*/
271   phOsali_ListDeleteAllNodes(psListCtxt);
272 
273   { /*Free up memory to queue context*/
274 
275     psListCtxt->sListCreateParams.MemFreeCb(
276         psListCtxt->sListCreateParams.memHdl, psListCtxt);
277 
278     psListCtxt = NULL;
279   }
280 
281   return OSALSTATUS_SUCCESS;
282 }
283 
284 /**
285  * Flush all objects/nodes in the linked list
286  */
phOsal_ListFlush(void * pvListHandle)287 OSALSTATUS phOsal_ListFlush(void* pvListHandle) {
288   phOsal_ListCtxt_t* psListCtxt = (phOsal_ListCtxt_t*)pvListHandle;
289   /*Validity check*/
290   if (NULL == pvListHandle) {
291     return OSALSTATUS_INVALID_PARAMS;
292   } /*if(NULL == pvListHandle)*/
293 
294   /*Delete all nodes*/
295   phOsali_ListDeleteAllNodes(psListCtxt);
296 
297   /*Update the link list context*/
298   psListCtxt->psHead = NULL;
299   psListCtxt->psTail = NULL;
300   psListCtxt->dwNumNodes = 0;
301 
302   return OSALSTATUS_SUCCESS;
303 }
304 
305 /**
306  * Flush all objects/nodes in the linked list
307  */
phOsali_ListDeleteAllNodes(void * pvListHandle)308 OSALSTATUS phOsali_ListDeleteAllNodes(void* pvListHandle) {
309   phOsal_ListCtxt_t* psListCtxt = (phOsal_ListCtxt_t*)pvListHandle;
310   phOsal_ListNode_t* psNodeTbd = NULL; /*Node to be deleted*/
311 
312   /*Delete all nodes*/
313   if (psListCtxt->psHead) { /*Atleast one element exists in the list*/
314     while (NULL !=
315            psListCtxt->psHead) { /*Delete all nodes until head becomes null*/
316       psNodeTbd = psListCtxt->psHead;
317 
318       psListCtxt->psHead = psListCtxt->psHead->ps_next;
319 
320       /*Free up memory of the node to be deleted*/
321       psListCtxt->sListCreateParams.MemFreeCb(
322           psListCtxt->sListCreateParams.memHdl, psNodeTbd);
323     } /*while(NULL != psListCtxt->psHead)*/
324   }   /*if(psListCtxt->psHead)*/
325 
326   return OSALSTATUS_SUCCESS;
327 }
328 
329 /* nothing past this point */
330