src/stringlist.c
author Krista Grothoff <krista@pep-project.org>
Mon, 11 Jul 2016 17:04:45 +0200
changeset 836 8e7dac747b49
parent 828 ea7e5920eda3
child 843 b1695eef237b
permissions -rw-r--r--
fix #94: _list_append behaviour on NULL list head is now to return NULL (both for stringpair_list_append and stringlist_append)
     1 #include "pEp_internal.h"
     2 
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <assert.h>
     6 
     7 #include "stringlist.h"
     8 
     9 
    10 DYNAMIC_API stringlist_t *new_stringlist(const char *value)
    11 {
    12     stringlist_t *result = calloc(1, sizeof(stringlist_t));
    13     assert(result);
    14 
    15     if (result && value) {
    16         result->value = strdup(value);
    17         assert(result->value);
    18         if (result->value == 0) {
    19             free(result);
    20             return NULL;
    21         }
    22         result->next = NULL; // needed for one-element lists
    23     }
    24 
    25     return result;
    26 }
    27 
    28 DYNAMIC_API stringlist_t *stringlist_dup(const stringlist_t *src)
    29 {
    30     assert(src);
    31     if (src == NULL)
    32         return NULL;
    33 
    34     stringlist_t *dst = new_stringlist(src->value);
    35     if (dst == NULL)
    36         return NULL;
    37 
    38     stringlist_t* src_curr = src->next;
    39     stringlist_t** dst_curr_ptr = &dst->next;
    40     
    41     while (src_curr) {
    42         *dst_curr_ptr = new_stringlist(src_curr->value);
    43         src_curr = src_curr->next;
    44         dst_curr_ptr = &((*dst_curr_ptr)->next);
    45     }
    46 
    47     return dst;
    48 }
    49 
    50 DYNAMIC_API stringlist_t *stringlist_add(
    51         stringlist_t *stringlist,
    52         const char *value
    53     )
    54 {  
    55     assert(value);
    56 
    57     if (stringlist == NULL)
    58         return new_stringlist(value);
    59 
    60     stringlist_t* list_curr = stringlist;
    61     
    62     while (list_curr->next)
    63         list_curr = list_curr->next;
    64  
    65     // if list end exists without value,
    66     // we fill it in here instead of adding
    67     // a new node.
    68     if (list_curr->value == NULL) {
    69         list_curr->value = strdup(value);
    70         assert(list_curr->value);
    71         if (list_curr->value == NULL)
    72             return NULL;
    73         return list_curr;
    74     }
    75     
    76     list_curr->next = new_stringlist(value);
    77 
    78     assert(list_curr->next);
    79     if (list_curr->next == NULL)
    80         return NULL;
    81 
    82     return list_curr->next;
    83 }
    84 
    85 DYNAMIC_API stringlist_t *stringlist_append(
    86         stringlist_t *stringlist,
    87         stringlist_t *second
    88     )
    89 {
    90     assert(stringlist);
    91     if (stringlist == NULL)
    92         return NULL;
    93 
    94     if (second == NULL || second->value == NULL)
    95         return stringlist;
    96 
    97     stringlist_t *_s = stringlist;
    98     stringlist_t *_s2;
    99     for (_s2 = second; _s2 != NULL; _s2 = _s2->next) {
   100         _s = stringlist_add(_s, _s2->value);
   101         if (_s == NULL)
   102             return NULL;
   103     }
   104     return _s;
   105 }
   106 
   107 DYNAMIC_API int stringlist_length(const stringlist_t *stringlist)
   108 {
   109     int len = 0;
   110 
   111     const stringlist_t *_sl;
   112     for (_sl = stringlist; _sl && _sl->value; _sl = _sl->next)
   113         len++;
   114 
   115     return len;
   116 }
   117 
   118 DYNAMIC_API stringlist_t *stringlist_delete(
   119         stringlist_t *stringlist,
   120         const char *value
   121     )
   122 {
   123     assert(stringlist);
   124     assert(value);
   125 
   126     if (stringlist->value == NULL) {
   127         free_stringlist(stringlist);
   128         return NULL;
   129     }
   130 
   131     if (value == NULL)
   132         return stringlist;
   133 
   134     stringlist_t *_sl;
   135     stringlist_t *last = NULL;
   136     for (_sl = stringlist; _sl && _sl->value; _sl = _sl->next) {
   137         if (strcmp(_sl->value, value) == 0) {
   138             if (last == NULL)
   139                 stringlist = stringlist->next;
   140             else
   141                 last->next = _sl->next;
   142             _sl->next = NULL;
   143             free_stringlist(_sl);
   144             break;
   145         }
   146         last = _sl;
   147     }
   148     return stringlist;
   149 }
   150 
   151 DYNAMIC_API void free_stringlist(stringlist_t *stringlist)
   152 {
   153     stringlist_t *curr;
   154     stringlist_t *next;
   155     
   156     curr = stringlist;
   157     
   158     while (curr) {
   159         next = curr->next;
   160         free(curr->value);
   161         free(curr);
   162         curr = next;
   163     }
   164 }
   165