src/stringlist.c
author Roker <roker@pep-project.org>
Thu, 26 Jan 2017 19:07:45 +0100
changeset 1559 c6506bc6a0df
parent 1513 e7f7e42385b5
child 1615 858298055d48
permissions -rw-r--r--
avoid unitialized local pointer variables to reduce hard-to-find bugs
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include "pEp_internal.h"
     5 
     6 #include <stdlib.h>
     7 #include <string.h>
     8 #include <assert.h>
     9 
    10 #include "stringlist.h"
    11 
    12 
    13 DYNAMIC_API stringlist_t *new_stringlist(const char *value)
    14 {
    15     stringlist_t *result = calloc(1, sizeof(stringlist_t));
    16     assert(result);
    17 
    18     if (result && value) {
    19         result->value = strdup(value);
    20         assert(result->value);
    21         if (result->value == 0) {
    22             free(result);
    23             return NULL;
    24         }
    25     }
    26 
    27     return result;
    28 }
    29 
    30 DYNAMIC_API stringlist_t *stringlist_dup(const stringlist_t *src)
    31 {
    32     assert(src);
    33     if (src == NULL)
    34         return NULL;
    35 
    36     stringlist_t *dst = new_stringlist(src->value);
    37     if (dst == NULL)
    38         return NULL;
    39 
    40     stringlist_t* src_curr = src->next;
    41     stringlist_t** dst_curr_ptr = &dst->next;
    42     
    43     while (src_curr) {
    44         *dst_curr_ptr = new_stringlist(src_curr->value);
    45         if (*dst_curr_ptr == NULL) {
    46             free_stringlist(dst);
    47             return NULL;
    48         }
    49         src_curr = src_curr->next;
    50         dst_curr_ptr = &((*dst_curr_ptr)->next);
    51     }
    52 
    53     return dst;
    54 }
    55 
    56 DYNAMIC_API stringlist_t *stringlist_add(
    57         stringlist_t *stringlist,
    58         const char *value
    59     )
    60 {  
    61     assert(value);
    62     if (value == NULL)
    63         return NULL;
    64 
    65     // empty list (no nodes)
    66     if (stringlist == NULL)
    67         return new_stringlist(value);
    68 
    69     // empty list (one node, no value)
    70     if (stringlist->value == NULL) {
    71         if (stringlist->next) 
    72             return NULL; // invalid list
    73             
    74         stringlist->value = strdup(value);
    75         assert(stringlist->value);
    76         
    77         if (stringlist->value == NULL)
    78             return NULL;
    79         
    80         return stringlist;
    81     }
    82     
    83     stringlist_t* list_curr = stringlist;
    84 
    85     while (list_curr->next)
    86         list_curr = list_curr->next;
    87      
    88     list_curr->next = new_stringlist(value);
    89 
    90     assert(list_curr->next);
    91     if (list_curr->next == NULL)
    92         return NULL;
    93 
    94     return list_curr->next;
    95 }
    96 
    97 DYNAMIC_API stringlist_t *stringlist_append(
    98         stringlist_t *stringlist,
    99         stringlist_t *second
   100     )
   101 {
   102     assert(stringlist);
   103     if (stringlist == NULL)
   104         return NULL;
   105 
   106     // Second list is empty
   107     if (second == NULL || second->value == NULL)
   108         return stringlist;
   109 
   110     stringlist_t *_s = stringlist;
   111     stringlist_t *_s2;
   112     for (_s2 = second; _s2 != NULL; _s2 = _s2->next) {
   113         _s = stringlist_add(_s, _s2->value);
   114         if (_s == NULL)
   115             return NULL;
   116     }
   117     return _s;
   118 }
   119 
   120 DYNAMIC_API int stringlist_length(const stringlist_t *stringlist)
   121 {
   122     int len = 0;
   123 
   124     const stringlist_t *_sl;
   125     for (_sl = stringlist; _sl && _sl->value; _sl = _sl->next)
   126         len++;
   127 
   128     return len;
   129 }
   130 
   131 DYNAMIC_API stringlist_t *stringlist_delete(
   132         stringlist_t *stringlist,
   133         const char *value
   134     )
   135 {
   136     assert(stringlist);
   137     assert(value);
   138 
   139     if (stringlist->value == NULL) {
   140         free_stringlist(stringlist);
   141         return NULL;
   142     }
   143 
   144     if (value == NULL)
   145         return stringlist;
   146 
   147     stringlist_t *_sl;
   148     stringlist_t *last = NULL;
   149     for (_sl = stringlist; _sl && _sl->value; _sl = _sl->next) {
   150         if (strcmp(_sl->value, value) == 0) {
   151             if (last == NULL)
   152                 stringlist = stringlist->next;
   153             else
   154                 last->next = _sl->next;
   155             _sl->next = NULL;
   156             free_stringlist(_sl);
   157             break;
   158         }
   159         last = _sl;
   160     }
   161     return stringlist;
   162 }
   163 
   164 DYNAMIC_API void free_stringlist(stringlist_t *stringlist)
   165 {
   166     stringlist_t *curr = stringlist;;
   167     
   168     while (curr) {
   169         stringlist_t *next = curr->next;
   170         free(curr->value);
   171         free(curr);
   172         curr = next;
   173     }
   174 }
   175