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-03-13 16:41:56 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         228 : mlist_t         *list_add_member(mlist_t *list, void *member, u32_t size) {
      34             :         mlist_t         *n_member, *tmp;
      35             : 
      36         228 :         if (member == NULL || size <= 0)
      37           2 :                 return NULL;
      38             : 
      39             :         /* Allocate the list container and the new member */
      40         226 :         n_member = malloc(sizeof(mlist_t));
      41         226 :         n_member->member = malloc(size);
      42         226 :         assert(n_member && n_member->member);
      43             : 
      44             :         /* Copy the new member */
      45         226 :         memcpy(n_member->member, member, size);
      46         226 :         n_member->size = size;
      47         226 :         n_member->next = n_member->prev = NULL;
      48             : 
      49             :         /* If the list head is NULL, we return the new */
      50         226 :         if (list == NULL) {
      51          46 :                 n_member->head = n_member;
      52          46 :                 return n_member;
      53             :         }
      54             : 
      55             :         /* Else, we go the end of the list */
      56         180 :         for (tmp = list; tmp->next != NULL; tmp = tmp->next)
      57             :                 ;
      58         180 :         tmp->next = n_member;
      59         180 :         n_member->prev = tmp;
      60         180 :         n_member->head = list;
      61         180 :         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          10 : mlist_t         *list_get_last(mlist_t *list) {
      71             :         mlist_t         *tmp;
      72             : 
      73          10 :         if (list == NULL)
      74           2 :                 return NULL;
      75           8 :         for (tmp = list; tmp->next; tmp = tmp->next)
      76             :                 ;
      77           8 :         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           6 : 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           6 :         n_member = malloc(sizeof(mlist_t));
      96           6 :         n_member->member = malloc(size);
      97           6 :         assert(n_member && n_member->member);
      98             : 
      99             :         /* Copy the new member */
     100           6 :         memcpy(n_member->member, member, size);
     101           6 :         n_member->size = size;
     102           6 :         n_member->next = n_member->prev = NULL;
     103             : 
     104             :         /* If the list head is NULL, we return the new member */
     105           6 :         if (org == NULL) {
     106           2 :                 n_member->head = n_member;
     107           2 :                 return n_member;
     108             :         }
     109             : 
     110             :         /* Search for the given ptr */
     111           4 :         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           4 :         if (tmp->next == NULL) {
     116           2 :                 tmp->next = n_member;
     117           2 :                 n_member->prev = tmp;
     118             :         } else {
     119           2 :                 tmp2 = tmp->next;
     120           2 :                 tmp->next = n_member;
     121           2 :                 n_member->prev = tmp;
     122           2 :                 n_member->next = tmp2;
     123           2 :                 tmp2->prev = n_member;
     124             :         }
     125           4 :         n_member->head = org;
     126           4 :         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           8 : 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           8 :         n_member = malloc(sizeof(mlist_t));
     147           8 :         n_member->member = malloc(size);
     148           8 :         assert(n_member && n_member->member);
     149             : 
     150             :         /* Copy the new member */
     151           8 :         memcpy(n_member->member, member, size);
     152           8 :         n_member->size = size;
     153           8 :         n_member->next = n_member->prev = NULL;
     154             : 
     155             :         /* If the list is NULL, we return the new member */
     156           8 :         if (org == NULL) {
     157           2 :                 n_member->head = n_member;
     158           2 :                 return n_member;
     159             :         }
     160             : 
     161             :         /* Search for the given ptr */
     162           6 :         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           6 :         if (tmp->next == NULL) {
     167           2 :                 tmp->next = n_member;
     168           2 :                 n_member->prev = tmp;
     169             : 
     170             :         /* If the given ptr is the head, replace the head by the new member */
     171           4 :         } else if (ptr == org) {
     172           2 :                 n_member->next = org;
     173           2 :                 n_member->prev = NULL;
     174           2 :                 org->prev = n_member;
     175           2 :                 org = n_member;
     176             :         } else {
     177           2 :                 tmp2 = tmp->prev;
     178           2 :                 n_member->next = tmp;
     179           2 :                 tmp->prev = n_member;
     180           2 :                 tmp2->next = n_member;
     181             :         }
     182           6 :         n_member->head = org;
     183           6 :         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           4 : u32_t           list_size(mlist_t *list) {
     192             :         u32_t           i;
     193             :         mlist_t         *tmp;
     194             : 
     195           4 :         if (list == NULL)
     196           2 :                 return 0;
     197             : 
     198           2 :         for (tmp = list, i = 0; tmp != NULL; tmp = tmp->next, i++)
     199             :                 ;
     200           2 :         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          42 : mlist_t         *list_free(mlist_t *list, int (*free_fn)(void *member)) {
     218          42 :         mlist_t         *tmp = list, *tmp2;
     219             : 
     220         304 :         while (tmp != NULL) {
     221         222 :                 tmp2 = tmp->next;
     222         222 :                 if (free_fn != NULL && free_fn(tmp->member) == 0) {
     223           2 :                         return tmp;
     224             :                 } else {
     225         220 :                         free(tmp->member);
     226         220 :                         free(tmp);
     227             :                 }
     228         220 :                 tmp = tmp2;
     229             :         }
     230          40 :         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         126 : void            *list_get(mlist_t *list, void *member, size_t size) {
     244             :         mlist_t         *tmp;
     245             :         void            *ptr;
     246             : 
     247         126 :         if (list == NULL)
     248           4 :                 return NULL;
     249         262 :         list_for_each(list, tmp, ptr) {
     250         256 :                 if (memcmp(ptr, member, size) == 0 && (size == tmp->size))
     251         116 :                         return ptr;
     252             :         }
     253           6 :         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           8 : 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           8 :         if (list == NULL)
     271           2 :                 return NULL;
     272             : 
     273             :         /* Search for the member */
     274          12 :         list_for_each(list, tmp2, ptr) {
     275          10 :                 if (memcmp(member, ptr, size) == 0)
     276           4 :                         break ;
     277             :         }
     278             : 
     279             :         /* We can't find the member */
     280           6 :         if (tmp2 == NULL) {
     281           2 :                 return list;
     282             :         }
     283             : 
     284           4 :         if (tmp2 == list) {
     285             :                 /* Replace the head */
     286           2 :                 list = tmp2->next;
     287             : 
     288             :                 /* Update the head in all other members */
     289           6 :                 list_for_each(list, tmp, ptr) {
     290           4 :                         tmp->head = list;
     291             :                 }
     292             :         } else {
     293           2 :                 tmp2->prev->next = tmp2->next;
     294             :         }
     295             : 
     296           4 :         if (free_fn != NULL) {
     297           2 :                 free_fn(tmp2->member);
     298             :         } else {
     299           2 :                 free(tmp2->member);
     300             :         }
     301           4 :         free(tmp2);
     302           4 :         return list;
     303             : }

Generated by: LCOV version 1.11