root/lib/util/util_strlist.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. str_list_make
  2. str_list_make_shell
  3. str_list_join
  4. str_list_join_shell
  5. str_list_length
  6. str_list_copy
  7. str_list_equal
  8. str_list_add
  9. str_list_remove
  10. str_list_check
  11. str_list_check_ci

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    
   4    Copyright (C) Andrew Tridgell 2005
   5    Copyright (C) Jelmer Vernooij 2005
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "system/locale.h"
  23 
  24 #undef strcasecmp
  25 
  26 /**
  27  * @file
  28  * @brief String list manipulation
  29  */
  30 
  31 /**
  32   build a null terminated list of strings from a input string and a
  33   separator list. The separator list must contain characters less than
  34   or equal to 0x2f for this to work correctly on multi-byte strings
  35 */
  36 _PUBLIC_ char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
     /* [<][>][^][v][top][bottom][index][help] */
  37 {
  38         int num_elements = 0;
  39         char **ret = NULL;
  40 
  41         if (sep == NULL) {
  42                 sep = LIST_SEP;
  43         }
  44 
  45         ret = talloc_array(mem_ctx, char *, 1);
  46         if (ret == NULL) {
  47                 return NULL;
  48         }
  49 
  50         while (string && *string) {
  51                 size_t len = strcspn(string, sep);
  52                 char **ret2;
  53                 
  54                 if (len == 0) {
  55                         string += strspn(string, sep);
  56                         continue;
  57                 }
  58 
  59                 ret2 = talloc_realloc(mem_ctx, ret, char *, num_elements+2);
  60                 if (ret2 == NULL) {
  61                         talloc_free(ret);
  62                         return NULL;
  63                 }
  64                 ret = ret2;
  65 
  66                 ret[num_elements] = talloc_strndup(ret, string, len);
  67                 if (ret[num_elements] == NULL) {
  68                         talloc_free(ret);
  69                         return NULL;
  70                 }
  71 
  72                 num_elements++;
  73                 string += len;
  74         }
  75 
  76         ret[num_elements] = NULL;
  77 
  78         return ret;
  79 }
  80 
  81 /**
  82  * build a null terminated list of strings from an argv-like input string 
  83  * Entries are seperated by spaces and can be enclosed by quotes. 
  84  * Does NOT support escaping
  85  */
  86 _PUBLIC_ const char **str_list_make_shell(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88         int num_elements = 0;
  89         const char **ret = NULL;
  90 
  91         ret = talloc_array(mem_ctx, const char *, 1);
  92         if (ret == NULL) {
  93                 return NULL;
  94         }
  95 
  96         if (sep == NULL)
  97                 sep = " \t\n\r";
  98 
  99         while (string && *string) {
 100                 size_t len = strcspn(string, sep);
 101                 char *element;
 102                 const char **ret2;
 103                 
 104                 if (len == 0) {
 105                         string += strspn(string, sep);
 106                         continue;
 107                 }
 108 
 109                 if (*string == '\"') {
 110                         string++;
 111                         len = strcspn(string, "\"");
 112                         element = talloc_strndup(ret, string, len);
 113                         string += len + 1;
 114                 } else {
 115                         element = talloc_strndup(ret, string, len);
 116                         string += len;
 117                 }
 118 
 119                 if (element == NULL) {
 120                         talloc_free(ret);
 121                         return NULL;
 122                 }
 123 
 124                 ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2);
 125                 if (ret2 == NULL) {
 126                         talloc_free(ret);
 127                         return NULL;
 128                 }
 129                 ret = ret2;
 130 
 131                 ret[num_elements] = element;    
 132 
 133                 num_elements++;
 134         }
 135 
 136         ret[num_elements] = NULL;
 137 
 138         return ret;
 139 
 140 }
 141 
 142 /**
 143  * join a list back to one string 
 144  */
 145 _PUBLIC_ char *str_list_join(TALLOC_CTX *mem_ctx, const char **list, char seperator)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147         char *ret = NULL;
 148         int i;
 149         
 150         if (list[0] == NULL)
 151                 return talloc_strdup(mem_ctx, "");
 152 
 153         ret = talloc_strdup(mem_ctx, list[0]);
 154 
 155         for (i = 1; list[i]; i++) {
 156                 ret = talloc_asprintf_append_buffer(ret, "%c%s", seperator, list[i]);
 157         }
 158 
 159         return ret;
 160 }
 161 
 162 /** join a list back to one (shell-like) string; entries 
 163  * seperated by spaces, using quotes where necessary */
 164 _PUBLIC_ char *str_list_join_shell(TALLOC_CTX *mem_ctx, const char **list, char sep)
     /* [<][>][^][v][top][bottom][index][help] */
 165 {
 166         char *ret = NULL;
 167         int i;
 168         
 169         if (list[0] == NULL)
 170                 return talloc_strdup(mem_ctx, "");
 171 
 172         if (strchr(list[0], ' ') || strlen(list[0]) == 0) 
 173                 ret = talloc_asprintf(mem_ctx, "\"%s\"", list[0]);
 174         else 
 175                 ret = talloc_strdup(mem_ctx, list[0]);
 176 
 177         for (i = 1; list[i]; i++) {
 178                 if (strchr(list[i], ' ') || strlen(list[i]) == 0) 
 179                         ret = talloc_asprintf_append_buffer(ret, "%c\"%s\"", sep, list[i]);
 180                 else 
 181                         ret = talloc_asprintf_append_buffer(ret, "%c%s", sep, list[i]);
 182         }
 183 
 184         return ret;
 185 }
 186 
 187 /**
 188   return the number of elements in a string list
 189 */
 190 _PUBLIC_ size_t str_list_length(const char * const*list)
     /* [<][>][^][v][top][bottom][index][help] */
 191 {
 192         size_t ret;
 193         for (ret=0;list && list[ret];ret++) /* noop */ ;
 194         return ret;
 195 }
 196 
 197 
 198 /**
 199   copy a string list
 200 */
 201 _PUBLIC_ char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list)
     /* [<][>][^][v][top][bottom][index][help] */
 202 {
 203         int i;
 204         char **ret;
 205 
 206         if (list == NULL)
 207                 return NULL;
 208         
 209         ret = talloc_array(mem_ctx, char *, str_list_length(list)+1);
 210         if (ret == NULL) 
 211                 return NULL;
 212 
 213         for (i=0;list && list[i];i++) {
 214                 ret[i] = talloc_strdup(ret, list[i]);
 215                 if (ret[i] == NULL) {
 216                         talloc_free(ret);
 217                         return NULL;
 218                 }
 219         }
 220         ret[i] = NULL;
 221         return ret;
 222 }
 223 
 224 /**
 225    Return true if all the elements of the list match exactly.
 226  */
 227 _PUBLIC_ bool str_list_equal(const char **list1, const char **list2)
     /* [<][>][^][v][top][bottom][index][help] */
 228 {
 229         int i;
 230         
 231         if (list1 == NULL || list2 == NULL) {
 232                 return (list1 == list2); 
 233         }
 234         
 235         for (i=0;list1[i] && list2[i];i++) {
 236                 if (strcmp(list1[i], list2[i]) != 0) {
 237                         return false;
 238                 }
 239         }
 240         if (list1[i] || list2[i]) {
 241                 return false;
 242         }
 243         return true;
 244 }
 245 
 246 
 247 /**
 248   add an entry to a string list
 249 */
 250 _PUBLIC_ const char **str_list_add(const char **list, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 251 {
 252         size_t len = str_list_length(list);
 253         const char **ret;
 254 
 255         ret = talloc_realloc(NULL, list, const char *, len+2);
 256         if (ret == NULL) return NULL;
 257 
 258         ret[len] = talloc_strdup(ret, s);
 259         if (ret[len] == NULL) return NULL;
 260 
 261         ret[len+1] = NULL;
 262 
 263         return ret;
 264 }
 265 
 266 /**
 267   remove an entry from a string list
 268 */
 269 _PUBLIC_ void str_list_remove(const char **list, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 270 {
 271         int i;
 272 
 273         for (i=0;list[i];i++) {
 274                 if (strcmp(list[i], s) == 0) break;
 275         }
 276         if (!list[i]) return;
 277 
 278         for (;list[i];i++) {
 279                 list[i] = list[i+1];
 280         }
 281 }
 282 
 283 
 284 /**
 285   return true if a string is in a list
 286 */
 287 _PUBLIC_ bool str_list_check(const char **list, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 288 {
 289         int i;
 290 
 291         for (i=0;list[i];i++) {
 292                 if (strcmp(list[i], s) == 0) return true;
 293         }
 294         return false;
 295 }
 296 
 297 /**
 298   return true if a string is in a list, case insensitively
 299 */
 300 _PUBLIC_ bool str_list_check_ci(const char **list, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 301 {
 302         int i;
 303 
 304         for (i=0;list[i];i++) {
 305                 if (strcasecmp(list[i], s) == 0) return true;
 306         }
 307         return false;
 308 }
 309 
 310 

/* [<][>][^][v][top][bottom][index][help] */