LCOV - code coverage report
Current view: top level - src - m_list.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 108 100.0 %
Date: 2017-02-27 17:05:36 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*********************************** LICENSE **********************************\
       2             : *                            Copyright 2017 Morphux                            *
       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             : #include <m_list.h>
      18             : 
      19             : /*!
      20             :  * \brief Add a new member to a linked list
      21             :  * \param list Head of a linked list
      22             :  * \param member New member to add
      23             :  * \param size Size of the new member
      24             :  *
      25             :  * This function will add the member at the end of the list. If the list
      26             :  * pointer is null, a new list head is returned.
      27             :  * Member is copied with a memcpy, in a pre-allocated pointer of size.
      28             :  *
      29             :  * \note If member is NULL, NULL is returned
      30             :  * \note If size is equal to 0, NULL is returned
      31             :  * \note Member is _not freed_ by this function
      32             :  */
      33         104 : mlist_t         *list_add_member(mlist_t *list, void *member, u32_t size) {
      34             :         mlist_t         *n_member, *tmp;
      35             : 
      36         104 :         if (member == NULL || size <= 0)
      37           1 :                 return NULL;
      38             : 
      39             :         /* Allocate the list container and the new member */
      40         103 :         n_member = malloc(sizeof(mlist_t));
      41         103 :         n_member->member = malloc(size);
      42         103 :         assert(n_member && n_member->member);
      43             : 
      44             :         /* Copy the new member */
      45         103 :         memcpy(n_member->member, member, size);
      46         103 :         n_member->size = size;
      47         103 :         n_member->next = n_member->prev = NULL;
      48             : 
      49             :         /* If the list head is NULL, we return the new */
      50         103 :         if (list == NULL) {
      51          17 :                 n_member->head = n_member;
      52          17 :                 return n_member;
      53             :         }
      54             : 
      55             :         /* Else, we go the end of the list */
      56          86 :         for (tmp = list; tmp->next != NULL; tmp = tmp->next)
      57             :                 ;
      58          86 :         tmp->next = n_member;
      59          86 :         n_member->prev = tmp;
      60          86 :         n_member->head = list;
      61          86 :         return list;
      62             : }
      63             : 
      64             : /*!
      65             :  * \brief Get list last member
      66             :  * \param list Head of the list
      67             :  * \return The last member of the list
      68             :  * \note If the list head is NULL, NULL is returned
      69             :  */
      70           5 : mlist_t         *list_get_last(mlist_t *list) {
      71             :         mlist_t         *tmp;
      72             : 
      73           5 :         if (list == NULL)
      74           1 :                 return NULL;
      75           4 :         for (tmp = list; tmp->next; tmp = tmp->next)
      76             :                 ;
      77           4 :         return tmp;
      78             : }
      79             : 
      80             : /*!
      81             :  * \brief Insert a new member after a given existing member in a list
      82             :  * \param org List head
      83             :  * \param ptr Pointer used to add member after
      84             :  * \param member New member to add
      85             :  * \param size Size of the new member
      86             :  *
      87             :  * This function will try to add a new member after a given ptr.
      88             :  * If list head is NULL, a new list is returned
      89             :  * If the given pointer is not in the list, the new member is added at the end
      90             :  */
      91           3 : mlist_t         *list_insert_after(mlist_t *org, mlist_t *ptr, void *member, u32_t size) {
      92             :         mlist_t         *n_member, *tmp, *tmp2;
      93             : 
      94             :         /* Allocate the new member */
      95           3 :         n_member = malloc(sizeof(mlist_t));
      96           3 :         n_member->member = malloc(size);
      97           3 :         assert(n_member && n_member->member);
      98             : 
      99             :         /* Copy the new member */
     100           3 :         memcpy(n_member->member, member, size);
     101           3 :         n_member->size = size;
     102           3 :         n_member->next = n_member->prev = NULL;
     103             : 
     104             :         /* If the list head is NULL, we return the new member */
     105           3 :         if (org == NULL) {
     106           1 :                 n_member->head = n_member;
     107           1 :                 return n_member;
     108             :         }
     109             : 
     110             :         /* Search for the given ptr */
     111           2 :         for (tmp = org; tmp->next && tmp != ptr; tmp = tmp->next)
     112             :                 ;
     113             : 
     114             :         /* If the ptr is not in the list, add the new member at the end of head */
     115           2 :         if (tmp->next == NULL) {
     116           1 :                 tmp->next = n_member;
     117           1 :                 n_member->prev = tmp;
     118             :         } else {
     119           1 :                 tmp2 = tmp->next;
     120           1 :                 tmp->next = n_member;
     121           1 :                 n_member->prev = tmp;
     122           1 :                 n_member->next = tmp2;
     123           1 :                 tmp2->prev = n_member;
     124             :         }
     125           2 :         n_member->head = org;
     126           2 :         return org;
     127             : }
     128             : 
     129             : /*!
     130             :  * \brief Insert a new member before a given existing member in a list
     131             :  * \param org List head
     132             :  * \param ptr Pointer used to add member after
     133             :  * \param member New member to add
     134             :  * \param size Size of the new member
     135             :  *
     136             :  * This function will try to add a new member before a given ptr
     137             :  * If list head is NULL, a new list is returned
     138             :  * If the given ptr is the current head, the head is updated with the new
     139             :  * member.
     140             :  * If the given ptr is not in the list, the member is added at the end
     141             :  */
     142           4 : mlist_t         *list_insert_before(mlist_t *org, mlist_t *ptr, void *member, u32_t size) {
     143             :         mlist_t         *n_member, *tmp, *tmp2;
     144             : 
     145             :         /* Allocate the new member */
     146           4 :         n_member = malloc(sizeof(mlist_t));
     147           4 :         n_member->member = malloc(size);
     148           4 :         assert(n_member && n_member->member);
     149             : 
     150             :         /* Copy the new member */
     151           4 :         memcpy(n_member->member, member, size);
     152           4 :         n_member->size = size;
     153           4 :         n_member->next = n_member->prev = NULL;
     154             : 
     155             :         /* If the list is NULL, we return the new member */
     156           4 :         if (org == NULL) {
     157           1 :                 n_member->head = n_member;
     158           1 :                 return n_member;
     159             :         }
     160             : 
     161             :         /* Search for the given ptr */
     162           3 :         for (tmp = org; tmp->next != NULL && tmp != ptr; tmp = tmp->next)
     163             :                 ;
     164             : 
     165             :         /* If the ptr is not in the list, add the new member at the end of head */
     166           3 :         if (tmp->next == NULL) {
     167           1 :                 tmp->next = n_member;
     168           1 :                 n_member->prev = tmp;
     169             : 
     170             :         /* If the given ptr is the head, replace the head by the new member */
     171           2 :         } else if (ptr == org) {
     172           1 :                 n_member->next = org;
     173           1 :                 n_member->prev = NULL;
     174           1 :                 org->prev = n_member;
     175           1 :                 org = n_member;
     176             :         } else {
     177           1 :                 tmp2 = tmp->prev;
     178           1 :                 n_member->next = tmp;
     179           1 :                 tmp->prev = n_member;
     180           1 :                 tmp2->next = n_member;
     181             :         }
     182           3 :         n_member->head = org;
     183           3 :         return org;
     184             : }
     185             : 
     186             : /*!
     187             :  * \brief Return the size of a list
     188             :  * \param list List head
     189             :  * \note If the list head is NULL, this function will return 0
     190             :  */
     191           2 : u32_t           list_size(mlist_t *list) {
     192             :         u32_t           i;
     193             :         mlist_t         *tmp;
     194             : 
     195           2 :         if (list == NULL)
     196           1 :                 return 0;
     197             : 
     198           1 :         for (tmp = list, i = 0; tmp != NULL; tmp = tmp->next, i++)
     199             :                 ;
     200           1 :         return i;
     201             : }
     202             : 
     203             : /*!
     204             :  * \brief Free a list
     205             :  * \param list List head
     206             :  * \param free_fn Function pointer to free the member
     207             :  *
     208             :  * This function will try to free a linked list.
     209             :  * free_fn function pointer is used to free the members.
     210             :  * This function must return something besides 0 in order to this function to
     211             :  * carry on.
     212             :  * If the free_fn function return 0, this function will stop, and return the 
     213             :  * current not-freed pointer.
     214             :  *
     215             :  * \return If the list has been entirely freed, this function will return NULL
     216             :  */
     217          21 : mlist_t         *list_free(mlist_t *list, int (*free_fn)(void *member)) {
     218          21 :         mlist_t         *tmp = list, *tmp2;
     219             : 
     220         150 :         while (tmp != NULL) {
     221         109 :                 tmp2 = tmp->next;
     222         109 :                 if (free_fn != NULL && free_fn(tmp->member) == 0) {
     223           1 :                         return tmp;
     224             :                 } else {
     225         108 :                         free(tmp->member);
     226         108 :                         free(tmp);
     227             :                 }
     228         108 :                 tmp = tmp2;
     229             :         }
     230          20 :         return NULL;
     231             : }
     232             : 
     233             : /*!
     234             :  * \brief Search a member in a list
     235             :  * \param list List head
     236             :  * \param member Member to search
     237             :  * \param size Size of the member
     238             :  *
     239             :  * Search member in list.
     240             :  * If member is found, return a pointer to it
     241             :  * If not, NULL is returned
     242             :  */
     243          61 : void            *list_get(mlist_t *list, void *member, size_t size) {
     244             :         mlist_t         *tmp;
     245             :         void            *ptr;
     246             : 
     247          61 :         if (list == NULL)
     248           2 :                 return NULL;
     249         127 :         list_for_each(list, tmp, ptr) {
     250         124 :                 if (memcmp(ptr, member, size) == 0 && (size == tmp->size))
     251          56 :                         return ptr;
     252             :         }
     253           3 :         return NULL;
     254             : }
     255             : 
     256             : /*!
     257             :  * \brief Remove a member from the list
     258             :  * \param list List head
     259             :  * \param member Member to remove
     260             :  * \param size Size of the member (Used for memcmp)
     261             :  * \param free_fn Function use to free the member
     262             :  *
     263             :  * Remove a member in a list.
     264             :  */
     265           4 : mlist_t         *list_remove(mlist_t *list, void *member, size_t size,
     266             :         int (*free_fn)(void *member)) {
     267             :         mlist_t         *tmp, *tmp2;
     268             :         void            *ptr;
     269             : 
     270           4 :         if (list == NULL)
     271           1 :                 return NULL;
     272             : 
     273             :         /* Search for the member */
     274           6 :         list_for_each(list, tmp2, ptr) {
     275           5 :                 if (memcmp(member, ptr, size) == 0)
     276           2 :                         break ;
     277             :         }
     278             : 
     279             :         /* We can't find the member */
     280           3 :         if (tmp2 == NULL) {
     281           1 :                 return list;
     282             :         }
     283             : 
     284           2 :         if (tmp2 == list) {
     285             :                 /* Replace the head */
     286           1 :                 list = tmp2->next;
     287             : 
     288             :                 /* Update the head in all other members */
     289           3 :                 list_for_each(list, tmp, ptr) {
     290           2 :                         tmp->head = list;
     291             :                 }
     292             :         } else {
     293           1 :                 tmp2->prev->next = tmp2->next;
     294             :         }
     295             : 
     296           2 :         if (free_fn != NULL) {
     297           1 :                 free_fn(tmp2->member);
     298             :         } else {
     299           1 :                 free(tmp2->member);
     300             :         }
     301           2 :         free(tmp2);
     302           2 :         return list;
     303             : }

Generated by: LCOV version 1.11