Migrated utils and trace to FVID2
[keystone-rtos/fvid2.git] / src / fvid2_utils.c
1 /*
2  *  Copyright (c) Texas Instruments Incorporated 2018
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    distribution.
15  *
16  *    Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /**
34  *  \file fvid2_utils.c
35  *
36  *  \brief Utility functions implementation file.
37  *  This file defines the helper functions like create, add and remove nodes
38  *
39  */
41 /* ========================================================================== */
42 /*                             Include Files                                  */
43 /* ========================================================================== */
45 #include <string.h>
46 #include <ti/drv/fvid2/fvid2.h>
48 /* ========================================================================== */
49 /*                           Macros & Typedefs                                */
50 /* ========================================================================== */
52 /* None */
54 /* ========================================================================== */
55 /*                         Structure Declarations                             */
56 /* ========================================================================== */
58 /* None */
60 /* ========================================================================== */
61 /*                          Function Declarations                             */
62 /* ========================================================================== */
64 static Fvid2Utils_Node *dutilsLinkCircularPri(Fvid2Utils_Node *headNode,
65                                               Fvid2Utils_Node *node,
66                                               void            *data,
67                                               uint32_t         priority);
68 static int32_t dutilsLinkDoublePri(Fvid2UtilsLinkListObj *llobj,
69                                    Fvid2Utils_Node       *node,
70                                    void                  *data,
71                                    uint32_t               priority,
72                                    uint32_t               linkUniqePriNodes);
73 static Fvid2Utils_Node *dutilsUnLinkCircularPri(Fvid2Utils_Node *headNode,
74                                                 Fvid2Utils_Node *node);
75 static void dutilsUnLinkDoublePri(Fvid2UtilsLinkListObj *llobj,
76                                   Fvid2Utils_Node       *node);
77 static Fvid2Utils_Node *dutilsUnLinkDouble(Fvid2UtilsLinkListObj *llobj,
78                                            Fvid2Utils_NodDir      dir,
79                                            const Fvid2Utils_Node *nodeToBeRem);
80 static Fvid2Utils_Node *dutilsLinkDouble(Fvid2UtilsLinkListObj *llobj,
81                                          Fvid2Utils_Node       *node,
82                                          void                  *data,
83                                          Fvid2Utils_NodDir      dir);
85 /* ========================================================================== */
86 /*                            Global Variables                                */
87 /* ========================================================================== */
89 /* None */
91 /* ========================================================================== */
92 /*                          Function Definitions                              */
93 /* ========================================================================== */
95 /**
96  *  Fvid2Utils_init
97  *  \brief Initializes the Util objects and create pool semaphore
98  *
99  *  \returns                Returns 0 on success else returns error value
100  */
101 int32_t Fvid2Utils_init(void)
103     return (FVID2_SOK);
106 /**
107  *  Fvid2Utils_deInit
108  *  \brief De-Initializes the Util objects by removing pool semaphore
109  *
110  *  \param arg              Not used currently. Meant for future purpose
111  *
112  *  \return                 Returns 0 on success else returns error value
113  */
114 int32_t Fvid2Utils_deInit(void *arg)
116     return (FVID2_SOK);
119 /**
120  *  Fvid2Utils_memset
121  *  \brief Sets the memory with the given value. Access memory as byte.
122  *  Returns the memory pointer.
123  *
124  *  \param mem              Destination memory pointer
125  *  \param ch               Byte value to fill with
126  *  \param byteCount        Number of bytes to fill
127  *
128  *  \return                 The destination memory pointer
129  */
130 void *Fvid2Utils_memset(void *mem, uint8_t ch, uint32_t byteCount)
132     /* NULL pointer check */
133     GT_assert(Fvid2Trace, (NULL != mem));
135     return memset(mem, (int32_t) ch, byteCount);
138 /**
139  *  Fvid2Utils_memsetw
140  *  \brief Sets the memory with the given value. Access memory as word.
141  *  Hence memory pointer should be aligned to 4 byte boundary
142  *  Returns the memory pointer.
143  *
144  *  \param mem              Destination memory pointer
145  *  \param word             Word value to fill with
146  *  \param wordCount        Number of words to fill
147  *
148  *  \return                 The destination memory pointer
149  */
150 void *Fvid2Utils_memsetw(void *mem, uint32_t word, uint32_t wordCount)
152     uint32_t  count;
153     uint32_t *memPtr = NULL;
155     /* NULL pointer check */
156     GT_assert(Fvid2Trace, (NULL != mem));
158     memPtr = (uint32_t *) mem;
159     for (count = 0; count < wordCount; count++)
160     {
161         memPtr[count] = word;
162     }
164     return (mem);
167 /**
168  *  Fvid2Utils_memcpy
169  *  \brief Copies source memory into destination memory. Access memory as byte.
170  *  Returns the destination memory pointer.
171  *
172  *  \param dest             Destination memory pointer
173  *  \param src              Source memory pointer
174  *  \param byteCount        Number of bytes to copy
175  *
176  *  \return                 The destination memory pointer
177  */
178 void *Fvid2Utils_memcpy(void *dest, const void *src, uint32_t byteCount)
180     /* NULL pointer check */
181     GT_assert(Fvid2Trace, (NULL != dest));
182     GT_assert(Fvid2Trace, (NULL != src));
184     return memcpy(dest, src, byteCount);
187 /**
188  *  Fvid2Utils_memcmp
189  *  \brief Compare memory block 1 with memory block 2. Access memory as byte.
190  *  Returns 0 if two memories are  identical.
191  *
192  *  \param mem1             memory block 1
193  *  \param mem2              memory block 2
194  *  \param byteCount        Number of bytes to compare
195  *
196  *  \return                 0 if two memory are identical other return 1
197  */
198 int32_t Fvid2Utils_memcmp(const void *mem1,
199                           const void *mem2,
200                           uint32_t byteCount)
202     /* NULL pointer check */
203     GT_assert(Fvid2Trace, (NULL != mem1));
204     GT_assert(Fvid2Trace, (NULL != mem2));
206     return memcmp(mem1, mem2, byteCount);
209 /**
210  *  Fvid2Utils_constructLinkList
211  *  \brief Constructs a link list object with the provided properties.
212  *
213  *  \param llobj pointer to object of type Fvid2UtilsLinkListObj
214  *  \param listType         List type - circular/double link list.
215  *  \param addMode          Node addition mode - Top/Bottom/Priority based.
216  *
217  *  \return                 Returns FVID2_SOK on success else returns error
218  *                          value.
219  */
220 int32_t Fvid2Utils_constructLinkList(Fvid2UtilsLinkListObj  *llobj,
221                                      Fvid2Utils_LinkListType listType,
222                                      Fvid2Utils_LinkAddMode  addMode)
224     int32_t retVal = FVID2_SOK;
225     if ((FVID2UTILS_LLT_CIRCULAR == listType) &&
226         (FVID2UTILS_LAM_PRIORITY != addMode))
227     {
228         GT_0trace(Fvid2Trace, GT_DEBUG,
229                   "Non-Priority circular link list not Supported\r\n");
230         retVal = FVID2_EBADARGS;
231     }
232     else
233     {
234         GT_assert(Fvid2Trace, (NULL != llobj));
235         /* Initialize the variables */
236         llobj->listType    = listType;
237         llobj->addMode     = addMode;
238         llobj->headNode    = NULL;
239         llobj->tailNode    = NULL;
240         llobj->numElements = 0U;
241         llobj->priorityCnt = 0;
242     }
244     return retVal;
247 /**
248  *  Fvid2Utils_destructLinkList
249  *  \brief Destructs a link list object.
250  *
251  *  \param llobj pointer to object of type Fvid2UtilsLinkListObj
252  *
253  *  \return                 Returns FVID2_SOK on success else returns error value.
254  */
255 int32_t Fvid2Utils_destructLinkList(Fvid2UtilsLinkListObj *llobj)
257     /* NULL pointer check */
258     GT_assert(Fvid2Trace, (NULL != llobj));
259     GT_assert(Fvid2Trace, (NULL == llobj->headNode));
260     GT_assert(Fvid2Trace, (NULL == llobj->tailNode));
262     /* Free link list object */
263     Fvid2Utils_memset(llobj, 0, sizeof (Fvid2UtilsLinkListObj));
265     return (FVID2_SOK);
268 /**
269  *  Fvid2Utils_unLinkAllNodes
270  *  \brief Releases all nodes without modifying any of the property.
271  *         CAUTION - Memory is NOT de-allocated, its the responsibility of the
272  *                   caller to ensure de-allocation of memory.
273  *
274  *  \param handle           Link list handle.
275  *
276  *  \return                 Returns 0 on success else returns error value.
277  */
278 int32_t Fvid2Utils_unLinkAllNodes(Fvid2Utils_Handle handle)
280     Fvid2UtilsLinkListObj *llobj;
282     /* NULL pointer check */
283     GT_assert(Fvid2Trace, (NULL != handle));
285     llobj              = (Fvid2UtilsLinkListObj *) handle;
286     llobj->headNode    = NULL;
287     llobj->tailNode    = NULL;
288     llobj->numElements = 0U;
289     llobj->priorityCnt = 0;
291     return (0);
294 /**
295  *  Fvid2Utils_linkNodePri
296  *  \brief Links a node to the linked list according to the list type
297  *  The memory to the node object should be allocated by the caller. This
298  *  is used for link list with priority.
299  *
300  *  \param handle           Link list handle.
301  *  \param node             Node object pointer used for linking.
302  *  \param priority         Priority of the node used for priority based
303  *                          addition of nodes. Priority is in descending order
304  *                          the value. So 0 is the highest priority and is
305  *                          added to the top of the node.
306  *                          Nodes with the same priority are always added to
307  *                          the bottom of the existing nodes with same
308  *                          priority.
309  *                          For non-priority based modes, this parameter
310  *                          is ignored and could be set to 0.
311  */
312 void Fvid2Utils_linkNodePri(Fvid2Utils_Handle handle,
313                             Fvid2Utils_Node  *node,
314                             uint32_t          priority)
316     Fvid2UtilsLinkListObj *llobj;
318     /* NULL pointer check */
319     GT_assert(Fvid2Trace, (NULL != handle));
320     GT_assert(Fvid2Trace, (NULL != node));
322     llobj = (Fvid2UtilsLinkListObj *) handle;
324     if (FVID2UTILS_LLT_CIRCULAR == llobj->listType)
325     {
326         llobj->headNode = dutilsLinkCircularPri(
327             llobj->headNode,
328             node,
329             node->data,
330             priority);
331     }
332     else if (FVID2UTILS_LLT_DOUBLE == llobj->listType)
333     {
334         dutilsLinkDoublePri(llobj, node, node->data, priority, (uint32_t) FALSE);
335     }
336     else
337     {
338         GT_assert(Fvid2Trace, FALSE);
339     }
341     return;
344 /**
345  *  Fvid2Utils_linkUniqePriNode
346  *  \brief Very similar to Fvid2Utils_linkNodePri, except that on equal priority
347  *          nodes will not be inserted. An error (FVID2_EBADARGS) would be
348  *          returned.
349  *          Applicable for double linked list only.
350  *
351  *  \param handle           Link list handle.
352  *  \param node             Node object pointer used for linking.
353  *  \param priority         Priority of the node used for priority based
354  *                          addition of nodes. Priority is in descending order
355  *                          the value. So 0 is the highest priority and is
356  *                          added to the top of the node.
357  *                          Nodes with the same priority are always added to
358  *                          the bottom of the existing nodes with same
359  *                          priority.
360  *                          For non-priority based modes, this parameter
361  *                          is ignored and could be set to 0.
362  */
363 int32_t Fvid2Utils_linkUniqePriNode(Fvid2Utils_Handle handle,
364                                     Fvid2Utils_Node  *node,
365                                     uint32_t          priority)
367     Fvid2UtilsLinkListObj *llobj;
368     int32_t rtnValue = FVID2_SOK;
370     /* NULL pointer check */
371     GT_assert(Fvid2Trace, (NULL != handle));
372     GT_assert(Fvid2Trace, (NULL != node));
374     llobj = (Fvid2UtilsLinkListObj *) handle;
376     if (FVID2UTILS_LAM_PRIORITY != llobj->addMode)
377     {
378         if (FVID2UTILS_LAM_TOP == llobj->addMode)
379         {
380             llobj->priorityCnt--;
381         }
382         else if (FVID2UTILS_LAM_BOTTOM == llobj->addMode)
383         {
384             llobj->priorityCnt++;
385         }
386         else
387         {
388             GT_assert(Fvid2Trace, FALSE);
389         }
390         priority = llobj->priorityCnt;
391     }
393     if (FVID2UTILS_LLT_CIRCULAR == llobj->listType)
394     {
395         llobj->headNode = dutilsLinkCircularPri(
396             llobj->headNode,
397             node,
398             node->data,
399             priority);
400     }
401     else if (FVID2UTILS_LLT_DOUBLE == llobj->listType)
402     {
403         rtnValue = dutilsLinkDoublePri(
404             llobj,
405             node,
406             node->data,
407             priority,
408             (uint32_t) TRUE);
409         if (rtnValue == FVID2_SOK)
410         {
411             llobj->numElements++;
412         }
413     }
414     else
415     {
416         GT_assert(Fvid2Trace, FALSE);
417     }
419     return (rtnValue);
422 /**
423  *  Fvid2Utils_unLinkNodePri
424  *  \brief Unlinks the node from the list. Used for the Priority linklists.
425  *
426  *  \param handle           Link list handle.
427  *  \param node             Node pointer to be unlinked from the list.
428  */
429 void Fvid2Utils_unLinkNodePri(Fvid2Utils_Handle handle, Fvid2Utils_Node *node)
431     Fvid2UtilsLinkListObj *llobj;
433     /* NULL pointer check */
434     GT_assert(Fvid2Trace, (NULL != handle));
435     GT_assert(Fvid2Trace, (NULL != node));
437     llobj = (Fvid2UtilsLinkListObj *) handle;
438     if (FVID2UTILS_LLT_CIRCULAR == llobj->listType)
439     {
440         llobj->headNode = dutilsUnLinkCircularPri(llobj->headNode, node);
441     }
442     else if (FVID2UTILS_LLT_DOUBLE == llobj->listType)
443     {
444         dutilsUnLinkDoublePri(llobj, node);
445     }
446     else
447     {
448         GT_assert(Fvid2Trace, FALSE);
449     }
451     return;
454 /**
455  *  Fvid2Utils_unLinkNode
456  *  \brief Unlinks the node from the list. Used for Non-priority linked lists
457  *
458  *  \param handle           Link list handle.
459  *  \param node             Node pointer to be unlinked from the list.
460  */
461 void Fvid2Utils_unLinkNode(Fvid2Utils_Handle handle, const Fvid2Utils_Node *node)
463     Fvid2UtilsLinkListObj *llobj;
464     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_HEAD;
466     /* NULL pointer check */
467     GT_assert(Fvid2Trace, (NULL != handle));
468     GT_assert(Fvid2Trace, (NULL != node));
470     llobj = (Fvid2UtilsLinkListObj *) handle;
471     dutilsUnLinkDouble(llobj, dir, node);
473     return;
476 /**
477  *  Fvid2Utils_linkNodeToTail
478  *  \brief                  Link the node to the tail of the double linked list.
479  *                          No priority
480  *
481  *  \param handle           Link list handle.
482  *  \param node             Node object pointer used for linking.
483  *  \param data             Data pointer to be added to the list.
484  *                          This should be unique.
485  *
486  */
487 void Fvid2Utils_linkNodeToTail(Fvid2Utils_Handle handle, Fvid2Utils_Node *node)
489     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_TAIL;
490     Fvid2UtilsLinkListObj *llobj;
492     /* NULL pointer check */
493     GT_assert(Fvid2Trace, (NULL != node));
494     GT_assert(Fvid2Trace, (NULL != handle));
496     llobj = (Fvid2UtilsLinkListObj *) handle;
497     dutilsLinkDouble(llobj, node, node->data, dir);
499     return;
502 /**
503  *  Fvid2Utils_linkNodeToHead
504  *  \brief                  Link the node to the head of the double linked list.
505  *                          No priority
506  *
507  *  \param handle           Link list handle.
508  *  \param node             Node object pointer used for linking.
509  *  \param data             Data pointer to be added to the list.
510  *                          This should be unique.
511  *
512  */
513 void Fvid2Utils_linkNodeToHead(Fvid2Utils_Handle handle, Fvid2Utils_Node *node)
515     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_HEAD;
516     Fvid2UtilsLinkListObj *llobj;
518     /* NULL pointer check */
519     GT_assert(Fvid2Trace, (NULL != node));
520     GT_assert(Fvid2Trace, (NULL != handle));
522     llobj = (Fvid2UtilsLinkListObj *) handle;
523     dutilsLinkDouble(llobj, node, node->data, dir);
525     return;
528 /**
529  *  Fvid2Utils_unLinkNodeFromHead
530  *  \brief                  Returns the node from head. Removes the  node from
531  *                          the list.
532  *
533  *  \param handle           Link list handle.
534  *  \param node             Node object pointer used for linking.
535  *  \param data             Data pointer to be added to the list.
536  *                          This should be unique.
537  *
538  */
539 Fvid2Utils_Node *Fvid2Utils_unLinkNodeFromHead(Fvid2Utils_Handle handle)
541     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_HEAD;
542     Fvid2UtilsLinkListObj *llobj;
544     /* NULL pointer check */
545     GT_assert(Fvid2Trace, (NULL != handle));
547     llobj = (Fvid2UtilsLinkListObj *) handle;
548     return (dutilsUnLinkDouble(llobj, dir, NULL));
551 /**
552  *  Fvid2Utils_unLinkNodeFromTail
553  *  \brief                  Returns the node from tail. Removes the  node from
554  *                          the list.
555  *
556  *  \param handle           Link list handle.
557  *  \param node             Node object pointer used for linking.
558  *  \param data             Data pointer to be added to the list.
559  *                          This should be unique.
560  *
561  */
562 Fvid2Utils_Node *Fvid2Utils_unLinkNodeFromTail(Fvid2Utils_Handle handle)
564     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_TAIL;
565     Fvid2UtilsLinkListObj *llobj;
567     /* NULL pointer check */
568     GT_assert(Fvid2Trace, (NULL != handle));
570     llobj = (Fvid2UtilsLinkListObj *) handle;
571     return (dutilsUnLinkDouble(llobj, dir, NULL));
574 /**
575  *  Fvid2Utils_getHeadNode
576  *  \brief                  Returns the reference to the headNode. Does
577  *                          not remove the node from the head.
578  *
579  *  \param handle           Link list handle.
580  *  \param node             Node object pointer used for linking.
581  *  \param data             Data pointer to be added to the list.
582  *                          This should be unique.
583  *
584  */
585 Fvid2Utils_Node *Fvid2Utils_getHeadNode(Fvid2Utils_Handle handle)
587     Fvid2UtilsLinkListObj *llobj;
589     /* NULL pointer check */
590     GT_assert(Fvid2Trace, (NULL != handle));
592     llobj = (Fvid2UtilsLinkListObj *) handle;
594     return (llobj->headNode);
597 /**
598  *  Fvid2Utils_getTailNode
599  *  \brief                  Returns the reference to the TailNode. Does
600  *                          not remove the node from the head.
601  *
602  *  \param handle           Link list handle.
603  *  \param node             Node object pointer used for linking.
604  *  \param data             Data pointer to be added to the list.
605  *                          This should be unique.
606  *
607  */
608 Fvid2Utils_Node *Fvid2Utils_getTailNode(Fvid2Utils_Handle handle)
610     Fvid2UtilsLinkListObj *llobj;
612     /* NULL pointer check */
613     GT_assert(Fvid2Trace, (NULL != handle));
615     llobj = (Fvid2UtilsLinkListObj *) handle;
616     return (llobj->tailNode);
619 /**
620  *  Fvid2Utils_isListEmpty
621  *  \brief Checks whether a list is empty or not.
622  *
623  *  \param handle           List handle.
624  *
625  *  \return                 TRUE if List is empty else returns FALSE.
626  */
627 uint32_t Fvid2Utils_isListEmpty(Fvid2Utils_Handle handle)
629     uint32_t isEmpty = FALSE;
630     Fvid2UtilsLinkListObj *llobj;
632     /* NULL pointer check */
633     GT_assert(Fvid2Trace, (NULL != handle));
635     llobj = (Fvid2UtilsLinkListObj *) handle;
636     if (NULL == llobj->headNode)
637     {
638         isEmpty = (uint32_t) TRUE;
639     }
641     return (isEmpty);
644 /**
645  *  Fvid2Utils_getNumNodes
646  *  \brief Returns the number of nodes present in a list.
647  *
648  *  \param handle           List handle.
649  *
650  *  \return                 Number of nodes present in a list.
651  */
652 uint32_t Fvid2Utils_getNumNodes(Fvid2Utils_Handle handle)
654     Fvid2Utils_Node       *node = NULL;
655     Fvid2UtilsLinkListObj *llobj;
656     uint32_t numNodes = 0U;
658     /* NULL pointer check */
659     GT_assert(Fvid2Trace, (NULL != handle));
661     llobj = (Fvid2UtilsLinkListObj *) handle;
662     if (FVID2UTILS_LLT_CIRCULAR == llobj->listType)
663     {
664         node = llobj->headNode;
665         while (NULL != node)
666         {
667             numNodes++;
668             node = node->next;
669             /* Not supposed to have NULL in circular list */
670             GT_assert(Fvid2Trace, (NULL != node));
672             /* Check if we have come to the end of the list */
673             if (node == llobj->headNode)
674             {
675                 break;
676             }
677         }
678     }
679     else if (FVID2UTILS_LLT_DOUBLE == llobj->listType)
680     {
681         node = llobj->headNode;
682         while (NULL != node)
683         {
684             numNodes++;
685             node = node->next;
686         }
687     }
688     else
689     {
690         GT_assert(Fvid2Trace, FALSE);
691     }
693     return (numNodes);
696 /**
697  *  Fvid2Utils_constructQ
698  *  \brief Constructs a Queue object.
699  *
700  * \param llobj pointer to object of type Fvid2UtilsLinkListObj
701  *
702  *  \return                 Returns FVID2_SOK on success else returns error value.
703  */
704 int32_t Fvid2Utils_constructQ(Fvid2UtilsLinkListObj *llobj)
706     return Fvid2Utils_constructLinkList(llobj, FVID2UTILS_LLT_DOUBLE,
707                                         FVID2UTILS_LAM_BOTTOM);
710 /**
711  *  Fvid2Utils_destructQ
712  *  \brief Destructs a Queue object.
713  *
714  * \param llobj pointer to object of type Fvid2UtilsLinkListObj
715  *
716  *  \return                 Returns FVID2_SOK on success else returns error value.
717  */
718 int32_t Fvid2Utils_destructQ(Fvid2UtilsLinkListObj *llobj)
720     return Fvid2Utils_destructLinkList(llobj);
723 /**
724  *  Fvid2Utils_queue
725  *  \brief Adds the data to the queue. Add the node to the tail of the queue.
726  *
727  *
728  *  \param handle           Queue handle.
729  *  \param qElem            Queue Element object pointer used for linking.
730  *  \param data             Data pointer to be added to the list.
731  *                          This should be unique.
732  */
733 void Fvid2Utils_queue(Fvid2Utils_QHandle handle,
734                       Fvid2Utils_QElem  *qElem,
735                       void              *data)
737     Fvid2UtilsLinkListObj *llobj;
738     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_TAIL;
740     /* NULL pointer check */
741     GT_assert(Fvid2Trace, (NULL != handle));
743     llobj = (Fvid2UtilsLinkListObj *) handle;
744     dutilsLinkDouble(llobj, qElem, data, dir);
746     return;
749 /**
750  *  Fvid2Utils_dequeue
751  *  \brief Removes a element from the queue. Removes the element from the head
752  *   of the queue.
753  *
754  *  \param handle           Queue handle.
755  *
756  *  \return                 Returns the removed data pointer.
757  */
758 void *Fvid2Utils_dequeue(Fvid2Utils_QHandle handle)
760     Fvid2Utils_Node       *node;
761     void                  *data = NULL;
762     Fvid2UtilsLinkListObj *llobj;
763     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_HEAD;
765     /* NULL pointer check */
766     GT_assert(Fvid2Trace, (NULL != handle));
768     llobj = (Fvid2UtilsLinkListObj *) handle;
769     node  = dutilsUnLinkDouble(llobj, dir, NULL);
770     if (NULL != node)
771     {
772         data = node->data;
773     }
774     else
775     {
776         data = NULL;
777     }
779     return (data);
782 /**
783  *  Fvid2Utils_peakHead
784  *  \brief Returns the reference of the first queued element.
785  *
786  *  This doesn't remove the element from the queue.
787  *  If the queue is empty, then this returns NULL.
788  *
789  *  \param handle           Queue handle.
790  *
791  *  \return                 Returns the reference of the first element.
792  */
793 void *Fvid2Utils_peakHead(Fvid2Utils_QHandle handle)
795     void *data = NULL;
796     Fvid2UtilsLinkListObj *llobj;
798     /* NULL pointer check */
799     GT_assert(Fvid2Trace, (NULL != handle));
801     llobj = (Fvid2UtilsLinkListObj *) handle;
802     if (llobj->headNode != NULL)
803     {
804         data = llobj->headNode->data;
805     }
807     return (data);
810 /**
811  *  Fvid2Utils_peakTail
812  *  \brief Returns the reference of the last queued element.
813  *
814  *  This doesn't remove the element from the queue.
815  *  If the queue is empty, then this returns NULL.
816  *
817  *  \param handle           Queue handle.
818  *
819  *  \return                 Returns the reference of the last queued element.
820  */
821 void *Fvid2Utils_peakTail(Fvid2Utils_QHandle handle)
823     void *data = NULL;
824     Fvid2UtilsLinkListObj *llobj;
826     /* NULL pointer check */
827     GT_assert(Fvid2Trace, (NULL != handle));
829     llobj = (Fvid2UtilsLinkListObj *) handle;
830     if (llobj->tailNode != NULL)
831     {
832         data = llobj->tailNode->data;
833     }
835     return (data);
838 /**
839  *  Fvid2Utils_queueBack
840  *  \brief Adds the data to start of the queue. Queue the data back to the
841  *  head of the queue.
842  *
843  *  \param handle           Queue handle.
844  *  \param qElem            Queue Element object pointer used for linking.
845  *  \param data             Data pointer to be added to the list.
846  *                          This should be unique.
847  */
848 void Fvid2Utils_queueBack(Fvid2Utils_QHandle handle,
849                           Fvid2Utils_QElem  *qElem,
850                           void              *data)
852     Fvid2UtilsLinkListObj *llobj;
853     Fvid2Utils_NodDir      dir = FVID2UTILS_NODE_DIR_HEAD;
855     /* NULL pointer check */
856     GT_assert(Fvid2Trace, (NULL != handle));
858     llobj = (Fvid2UtilsLinkListObj *) handle;
859     dutilsLinkDouble(llobj, qElem, data, dir);
861     return;
864 /**
865  *  Fvid2Utils_isQEmpty
866  *  \brief Checks whether a queue is empty or not.
867  *
868  *  \param handle           Queue handle.
869  *
870  *  \return                 TRUE if queue is empty else returns FALSE.
871  */
872 uint32_t Fvid2Utils_isQEmpty(Fvid2Utils_QHandle handle)
874     return Fvid2Utils_isListEmpty(handle);
877 /**
878  *  Fvid2Utils_getNumQElem
879  *  \brief Returns the number of Queue Elements present in a Queue.
880  *
881  *  \param handle           Queue handle.
882  *
883  *  \return                 Number of Queue Elements present in a Queue.
884  */
885 uint32_t Fvid2Utils_getNumQElem(Fvid2Utils_QHandle handle)
887     return Fvid2Utils_getNumNodes(handle);
890 /**
891  *  dutilsLinkCircularPri
892  *  \brief Links a node to a circular link list based on priority.
893  *  For nodes with same priority, the new node will be added to the last.
894  */
895 static Fvid2Utils_Node *dutilsLinkCircularPri(Fvid2Utils_Node *headNode,
896                                               Fvid2Utils_Node *node,
897                                               void            *data,
898                                               uint32_t         priority)
900     Fvid2Utils_Node *curNode;
902     /* NULL pointer check */
903     GT_assert(Fvid2Trace, (NULL != node));
905     node->data     = data;
906     node->priority = priority;
908     /* Check if this is the first node. */
909     if (NULL != headNode)
910     {
911         /* Add to the list based on priority */
912         curNode = headNode;
913         do
914         {
915             /* Nodes with the same priority are always added to the bottom
916              * of the existing nodes with same priority. */
917             if (priority < curNode->priority)
918             {
919                 if (curNode == headNode)
920                 {
921                     /* Adding to the top of the list */
922                     headNode = node;
923                 }
924                 break;
925             }
927             /* Move to next node */
928             curNode = curNode->next;
929             /* Not supposed to have NULL in circular list */
930             GT_assert(Fvid2Trace, (NULL != curNode));
931         } while (curNode != headNode);
932         /* Check if we have come to the end of the list */
934         /* Add the node before the current node as we have traversed one
935          * extra node. */
936         node->next = curNode;
937         node->prev = curNode->prev;
939         /* Not supposed to have NULL in circular list */
940         GT_assert(Fvid2Trace, (NULL != curNode->prev));
941         GT_assert(Fvid2Trace, (NULL != curNode->prev->next));
942         curNode->prev->next = node;
943         curNode->prev       = node;
944     }
945     else
946     {
947         /* First node. Add to as head node */
948         headNode   = node;
949         node->next = node;
950         node->prev = node;
951     }
953     return (headNode);
956 /**
957  *  dutilsLinkDoublePri
958  *  \brief Links a node to a double link list based on priority.
959  *  For nodes with same priority, the new node will be added to the last.
960  *
961  *  ToDo - Remove multiple return statements - Have one exit point for the
962  *         Function.
963  */
964 static int32_t dutilsLinkDoublePri(Fvid2UtilsLinkListObj *llobj,
965                                    Fvid2Utils_Node       *node,
966                                    void                  *data,
967                                    uint32_t               priority,
968                                    uint32_t               linkUniqePriNodes)
970     int32_t          retVal = FVID2_SOK;
971     Fvid2Utils_Node *curNode, *prevNode = NULL;
973     /* NULL pointer check */
974     GT_assert(Fvid2Trace, (NULL != node));
976     node->data     = data;
977     node->priority = priority;
979     /* Add to the list based on priority */
980     curNode = llobj->headNode;
981     while (NULL != curNode)
982     {
983         /* Nodes with the same priority are always added to the bottom
984          * of the existing nodes with same priority. */
985         if (priority < curNode->priority)
986         {
987             break;
988         }
990         /* Move to next node */
991         prevNode = curNode;
992         curNode  = curNode->next;
993     }
995     /* If unique priority check is enabled - check for uniqueness */
996     if (linkUniqePriNodes == (uint32_t) TRUE)
997     {
998         if (prevNode != NULL)
999         {
1000             if (priority == prevNode->priority)
1001             {
1002                 retVal = FVID2_EBADARGS;
1003             }
1004         }
1005     }
1007     if (FVID2_SOK == retVal)
1008     {
1009         /* Add the node between current and previous nodes */
1010         node->next = curNode;
1011         node->prev = prevNode;
1012         if (NULL != prevNode)
1013         {
1014             prevNode->next = node;
1015         }
1016         else
1017         {
1018             /* Adding to the top of the list */
1019             llobj->headNode = node;
1020         }
1022         if (NULL != curNode)
1023         {
1024             curNode->prev = node;
1025         }
1026         else
1027         {
1028             llobj->tailNode = node;
1029         }
1030         retVal = FVID2_SOK;
1031     }
1033     return (retVal);
1036 /**
1037  *  dutilsUnLinkCircularPri
1038  *  \brief Unlinks a node from a circular link list.
1039  */
1040 static Fvid2Utils_Node *dutilsUnLinkCircularPri(Fvid2Utils_Node *headNode,
1041                                                 Fvid2Utils_Node *node)
1043     /* NULL pointer check */
1044     GT_assert(Fvid2Trace, (NULL != headNode));
1045     GT_assert(Fvid2Trace, (NULL != node));
1047     /* Not supposed to have NULL in circular list */
1048     GT_assert(Fvid2Trace, (NULL != node->next));
1049     GT_assert(Fvid2Trace, (NULL != node->prev));
1051     /* Link the node's previous node to node's next node */
1052     node->prev->next = node->next;
1053     node->next->prev = node->prev;
1055     if (node == headNode)
1056     {
1057         /* Unlinking head node */
1058         if ((headNode == headNode->next) || (headNode == headNode->prev))
1059         {
1060             /* Unlinking last node */
1061             GT_assert(Fvid2Trace,
1062                       ((headNode == headNode->next) &&
1063                        (headNode == headNode->prev)));
1064             headNode = NULL;
1065         }
1066         else
1067         {
1068             /* Make next node as head node */
1069             headNode = node->next;
1070         }
1071     }
1073     /* Reset node memory */
1074     node->next = NULL;
1075     node->prev = NULL;
1077     return (headNode);
1080 /**
1081  *  dutilsUnLinkDoublePri
1082  *  \brief Unlinks a node from a double link list.
1083  */
1084 static void dutilsUnLinkDoublePri(Fvid2UtilsLinkListObj *llobj,
1085                                   Fvid2Utils_Node       *node)
1087     /* NULL pointer check */
1088     GT_assert(Fvid2Trace, (NULL != llobj));
1089     GT_assert(Fvid2Trace, (NULL != node));
1091     if (NULL == node->prev)
1092     {
1093         /* Removing head node */
1094         llobj->headNode = node->next;
1095     }
1096     else
1097     {
1098         /* Removing non-head node */
1099         node->prev->next = node->next;
1100     }
1102     if (NULL != node->next)
1103     {
1104         node->next->prev = node->prev;
1105     }
1106     else
1107     {
1108         llobj->tailNode = NULL;
1109     }
1111     /* Reset node memory */
1112     node->next = NULL;
1113     node->prev = NULL;
1115     return;
1118 /**
1119  *  dutilsUnLinkDouble
1120  *  \brief Unlinks a node from a double link list.
1121  */
1122 static Fvid2Utils_Node *dutilsUnLinkDouble(Fvid2UtilsLinkListObj *llobj,
1123                                            Fvid2Utils_NodDir      dir,
1124                                            const Fvid2Utils_Node *nodeToBeRem)
1126     Fvid2Utils_Node *node = NULL, *headNode, *tailNode, *listNode;
1127     uint32_t         nodeCnt;
1129     /* NULL pointer check */
1130     GT_assert(Fvid2Trace, (NULL != llobj));
1132     if (NULL == nodeToBeRem)
1133     {
1134         if ((NULL == llobj->headNode) && (NULL == llobj->tailNode))
1135         {
1136             node = NULL;
1137         }
1138         /* Check for the last node in the list */
1139         else if ((NULL != llobj->headNode) &&
1140                  (NULL == llobj->headNode->next) &&
1141                  (NULL == llobj->headNode->prev))
1142         {
1143             node = llobj->headNode;
1144             llobj->tailNode = NULL;
1145             llobj->headNode = NULL;
1146         }
1147         else if ((NULL != llobj->headNode) &&
1148                  (NULL != llobj->tailNode) &&
1149                  (FVID2UTILS_NODE_DIR_HEAD == dir))
1150         {
1151             /* Point headnode to the head of the list */
1152             headNode = llobj->headNode;
1153             /* headnode points to now next in the list */
1154             llobj->headNode = headNode->next;
1155             /* prev of the new headnode point to headNode of the list */
1156             if (NULL != llobj->headNode)
1157             {
1158                 llobj->headNode->prev = NULL;
1159             }
1160             else
1161             {
1162                 llobj->tailNode = NULL;
1163             }
1164             /* return the detached node */
1165             node = headNode;
1166         }
1167         else if ((NULL != llobj->headNode) &&
1168                  (NULL != llobj->tailNode) &&
1169                  (FVID2UTILS_NODE_DIR_TAIL == dir))
1170         {
1171             /* point to the tail node. */
1172             tailNode = llobj->tailNode;
1173             /* tailnode of the list points to the previous node */
1174             llobj->tailNode = tailNode->prev;
1175             /* next node of the previous node points to the tail node of list */
1176             if (NULL != llobj->tailNode)
1177             {
1178                 llobj->tailNode->next = NULL;
1179             }
1180             else
1181             {
1182                 llobj->headNode = NULL;
1183             }
1184             /*  return the tail node */
1185             node = tailNode;
1186         }
1187         else
1188         {
1189             GT_assert(Fvid2Trace, FALSE);
1190         }
1191     }
1192     else
1193     {
1194         listNode = llobj->headNode;
1195         for (nodeCnt = 0; nodeCnt < llobj->numElements; nodeCnt++)
1196         {
1197             if (listNode == nodeToBeRem)
1198             {
1199                 /* Last node in the list */
1200                 if ((llobj->headNode == listNode) &&
1201                     (llobj->tailNode == listNode))
1202                 {
1203                     llobj->headNode = NULL;
1204                     llobj->tailNode = NULL;
1205                 }
1206                 else if (llobj->headNode == listNode)
1207                 {
1208                     llobj->headNode       = listNode->next;
1209                     llobj->headNode->prev = NULL;
1210                 }
1211                 else if (llobj->tailNode == listNode)
1212                 {
1213                     llobj->tailNode       = listNode->prev;
1214                     llobj->tailNode->next = NULL;
1215                 }
1216                 else
1217                 {
1218                     listNode->prev->next = listNode->next;
1219                     listNode->next->prev = listNode->prev;
1220                 }
1221                 node = listNode;
1222                 break;
1223             }
1224             listNode = listNode->next;
1225         }
1226     }
1227     if (NULL != node)
1228     {
1229         /* Reset node memory */
1230         node->next = NULL;
1231         node->prev = NULL;
1232         llobj->numElements--;
1233     }
1235     return (node);
1238 /**
1239  *  Fvid2Utils_getNumNodes
1240  *  \brief Returns the number of nodes present in a list.
1241  *
1242  *  \param handle           List handle.
1243  *
1244  *  \return                 Number of nodes present in a list.
1245  */
1246 uint32_t Fvid2Utils_getNodeCnt(Fvid2Utils_Handle handle)
1248     /* NULL pointer check */
1249     GT_assert(Fvid2Trace, (NULL != handle));
1251     return (((Fvid2UtilsLinkListObj *) handle)->numElements);
1254 /**
1255  *  dutilsLinkDouble
1256  *  \brief Links a node to a double link list either at head of the list or
1257  *  at tail of the list.
1258  *
1259  *
1260  */
1261 static Fvid2Utils_Node *dutilsLinkDouble(Fvid2UtilsLinkListObj *llobj,
1262                                          Fvid2Utils_Node       *node,
1263                                          void                  *data,
1264                                          Fvid2Utils_NodDir      dir)
1266     Fvid2Utils_Node *headNode, *tailNode = NULL;
1268     /* NULL pointer check */
1269     GT_assert(Fvid2Trace, (NULL != node));
1270     GT_assert(Fvid2Trace, (NULL != llobj));
1272     node->data = data;
1273     /* check for the first element in the list */
1274     if ((NULL == llobj->headNode) && (NULL == llobj->tailNode))
1275     {
1276         /* Add the first element in the list */
1277         /* head node points to new element */
1278         llobj->headNode = node;
1279         /* tail node also points to new element */
1280         llobj->tailNode = node;
1281         /* next of node points to tail */
1282         node->next = NULL;
1283         /* prev of node points to head */
1284         node->prev = NULL;
1285     }
1286     else if ((NULL != llobj->headNode) &&
1287              (NULL != llobj->tailNode) &&
1288              (FVID2UTILS_NODE_DIR_HEAD == dir))
1289     {
1290         headNode = llobj->headNode;
1291         /* headNode now points to new node */
1292         llobj->headNode = node;
1293         /* previous of new node points to headNode */
1294         node->prev = NULL;
1295         /* next of new points to prev head node */
1296         node->next = headNode;
1297         /* prev of previous head node head points to new node */
1298         headNode->prev = node;
1299     }
1300     else if ((NULL != llobj->headNode) &&
1301              (NULL != llobj->tailNode) &&
1302              (FVID2UTILS_NODE_DIR_TAIL == dir))
1303     {
1304         tailNode = llobj->tailNode;
1305         /* next of new node points to tail of list */
1306         node->next = NULL;
1307         /* tail of list points to new node */
1308         llobj->tailNode = node;
1309         /* next of previous tial node points to new tail node */
1310         tailNode->next = node;
1311         /* previous of new tail node points to previous tail node */
1312         node->prev = tailNode;
1313     }
1314     else
1315     {
1316         GT_assert(Fvid2Trace, FALSE);
1317     }
1318     llobj->numElements++;
1319     return (node);