src/stringlist.c
author Krista Bennett <krista@pep-project.org>
Fri, 01 Jun 2018 10:30:19 +0200
branchENGINE-233
changeset 2727 b8b0443804da
parent 1694 032e59ccdd93
child 2963 a80bc5f9167e
permissions -rw-r--r--
close branch
     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 static bool _stringlist_add_first(
    57         stringlist_t *stringlist,
    58         stringlist_t **result,
    59         const char *value
    60     )
    61 {  
    62     // empty list (no nodes)
    63     if (stringlist == NULL) {
    64         *result = new_stringlist(value);
    65         return true;
    66     }
    67 
    68     // empty list (one node, no value)
    69     if (stringlist->value == NULL) {
    70         if (stringlist->next) {
    71             *result = NULL; // invalid list
    72             return true;
    73         } 
    74             
    75         stringlist->value = strdup(value);
    76         assert(stringlist->value);
    77         
    78         if (stringlist->value == NULL) {
    79             *result = NULL;
    80             return true;
    81         }
    82         
    83         *result = stringlist;
    84         return true;
    85     }
    86     return false;
    87 }
    88 
    89 DYNAMIC_API stringlist_t *stringlist_add(
    90         stringlist_t *stringlist,
    91         const char *value
    92     )
    93 {  
    94     assert(value);
    95     if (value == NULL)
    96         return NULL;
    97 
    98     stringlist_t *result = NULL;
    99     if(_stringlist_add_first(stringlist, &result, value))
   100         return result;
   101     
   102     stringlist_t* list_curr = stringlist;
   103 
   104     while (list_curr->next)
   105         list_curr = list_curr->next;
   106      
   107     list_curr->next = new_stringlist(value);
   108 
   109     assert(list_curr->next);
   110     if (list_curr->next == NULL)
   111         return NULL;
   112 
   113     return list_curr->next;
   114 }
   115 
   116 DYNAMIC_API stringlist_t *stringlist_add_unique(
   117         stringlist_t *stringlist,
   118         const char *value
   119     )
   120 {  
   121     assert(value);
   122     if (value == NULL)
   123         return NULL;
   124 
   125     stringlist_t *result = NULL;
   126     if(_stringlist_add_first(stringlist, &result, value))
   127         return result;
   128     
   129     stringlist_t* list_curr = stringlist;
   130 
   131     bool found = false;
   132     while (list_curr->next) {
   133         if(strcmp(list_curr->value,value)==0)
   134             found = true;
   135         list_curr = list_curr->next;
   136     }
   137      
   138     if (!found) {
   139         list_curr->next = new_stringlist(value);
   140 
   141         assert(list_curr->next);
   142         if (list_curr->next == NULL)
   143             return NULL;
   144 
   145         return list_curr->next;
   146     } else {
   147         return list_curr;
   148     }
   149 }
   150 
   151 
   152 DYNAMIC_API stringlist_t *stringlist_append(
   153         stringlist_t *stringlist,
   154         stringlist_t *second
   155     )
   156 {
   157     assert(stringlist);
   158     if (stringlist == NULL)
   159         return NULL;
   160 
   161     // Second list is empty
   162     if (second == NULL || second->value == NULL)
   163         return stringlist;
   164 
   165     stringlist_t *_s = stringlist;
   166     stringlist_t *_s2;
   167     for (_s2 = second; _s2 != NULL; _s2 = _s2->next) {
   168         _s = stringlist_add(_s, _s2->value);
   169         if (_s == NULL)
   170             return NULL;
   171     }
   172     return _s;
   173 }
   174 
   175 DYNAMIC_API int stringlist_length(const stringlist_t *stringlist)
   176 {
   177     int len = 0;
   178 
   179     const stringlist_t *_sl;
   180     for (_sl = stringlist; _sl && _sl->value; _sl = _sl->next)
   181         len++;
   182 
   183     return len;
   184 }
   185 
   186 DYNAMIC_API stringlist_t *stringlist_delete(
   187         stringlist_t *stringlist,
   188         const char *value
   189     )
   190 {
   191     assert(stringlist);
   192     assert(value);
   193 
   194     if (stringlist->value == NULL) {
   195         free_stringlist(stringlist);
   196         return NULL;
   197     }
   198 
   199     if (value == NULL)
   200         return stringlist;
   201 
   202     stringlist_t *_sl;
   203     stringlist_t *last = NULL;
   204     for (_sl = stringlist; _sl && _sl->value; _sl = _sl->next) {
   205         if (strcmp(_sl->value, value) == 0) {
   206             if (last == NULL)
   207                 stringlist = stringlist->next;
   208             else
   209                 last->next = _sl->next;
   210             _sl->next = NULL;
   211             free_stringlist(_sl);
   212             break;
   213         }
   214         last = _sl;
   215     }
   216     return stringlist;
   217 }
   218 
   219 DYNAMIC_API void free_stringlist(stringlist_t *stringlist)
   220 {
   221     stringlist_t *curr = stringlist;
   222     
   223     while (curr) {
   224         stringlist_t *next = curr->next;
   225         free(curr->value);
   226         curr->value = NULL;
   227         free(curr);
   228         curr = next;
   229     }
   230 }