r7052: added a case insensitive str_list_check_ci() version of str_list_check()
[sfrench/samba-autobuild/.git] / source4 / lib / util_strlist.c
index db459b2f0fc9d5e825c16b7b846fc29d530ccad9..d5c4d915850f345584b308c11d56c9a5a5d32d2e 100644 (file)
@@ -1,9 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
    
-   Copyright (C) Andrew Tridgell 1992-2004
-   Copyright (C) Simo Sorce      2001-2002
-   Copyright (C) Martin Pool     2003
+   Copyright (C) Andrew Tridgell 2005
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 #include "includes.h"
 
-/**
- List of Strings manipulation functions
-**/
+/*
+  build a null terminated list of strings from a input string and a
+  separator list. The sepatator list must contain characters less than
+  or equal to 0x2f for this to work correctly on multi-byte strings
+*/
+const char **str_list_make(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
+{
+       int num_elements = 0;
+       const char **ret = NULL;
 
-#define S_LIST_ABS 16 /* List Allocation Block Size */
+       if (sep == NULL) {
+               sep = LIST_SEP;
+       }
 
-char **str_list_make(const char *string, const char *sep)
-{
-       char **list, **rlist;
-       const char *str;
-       char *s;
-       int num, lsize;
-       pstring tok;
-       
-       if (!string || !*string)
-               return NULL;
-       s = strdup(string);
-       if (!s) {
-               DEBUG(0,("str_list_make: Unable to allocate memory"));
+       ret = talloc_array(mem_ctx, const char *, 1);
+       if (ret == NULL) {
                return NULL;
        }
-       if (!sep) sep = LIST_SEP;
-       
-       num = lsize = 0;
-       list = NULL;
-       
-       str = s;
-       while (next_token(&str, tok, sep, sizeof(tok))) {               
-               if (num == lsize) {
-                       lsize += S_LIST_ABS;
-                       rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
-                       if (!rlist) {
-                               DEBUG(0,("str_list_make: Unable to allocate memory"));
-                               str_list_free(&list);
-                               SAFE_FREE(s);
-                               return NULL;
-                       } else
-                               list = rlist;
-                       memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
-               }
+
+       while (string && *string) {
+               size_t len = strcspn(string, sep);
+               const char **ret2;
                
-               list[num] = strdup(tok);
-               if (!list[num]) {
-                       DEBUG(0,("str_list_make: Unable to allocate memory"));
-                       str_list_free(&list);
-                       SAFE_FREE(s);
+               if (len == 0) {
+                       string += strspn(string, sep);
+                       continue;
+               }
+
+               ret2 = talloc_realloc(mem_ctx, ret, const char *, num_elements+2);
+               if (ret2 == NULL) {
+                       talloc_free(ret);
                        return NULL;
                }
-       
-               num++;  
+               ret = ret2;
+
+               ret[num_elements] = talloc_strndup(ret, string, len);
+               if (ret[num_elements] == NULL) {
+                       talloc_free(ret);
+                       return NULL;
+               }
+
+               num_elements++;
+               string += len;
        }
-       
-       SAFE_FREE(s);
-       return list;
+
+       ret[num_elements] = NULL;
+
+       return ret;
 }
 
-BOOL str_list_copy(char ***dest, const char **src)
+/*
+  return the number of elements in a string list
+*/
+size_t str_list_length(const char **list)
 {
-       char **list, **rlist;
-       int num, lsize;
-       
-       *dest = NULL;
-       if (!src)
-               return False;
-       
-       num = lsize = 0;
-       list = NULL;
-               
-       while (src[num]) {
-               if (num == lsize) {
-                       lsize += S_LIST_ABS;
-                       rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
-                       if (!rlist) {
-                               DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
-                               str_list_free(&list);
-                               return False;
-                       } else
-                               list = rlist;
-                       memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
-               }
-               
-               list[num] = strdup(src[num]);
-               if (!list[num]) {
-                       DEBUG(0,("str_list_copy: Unable to allocate memory"));
-                       str_list_free(&list);
-                       return False;
-               }
+       size_t ret;
+       for (ret=0;list && list[ret];ret++) /* noop */ ;
+       return ret;
+}
+
 
-               num++;
+/*
+  copy a string list
+*/
+const char **str_list_copy(TALLOC_CTX *mem_ctx, const char **list)
+{
+       int i;
+       const char **ret = talloc_array(mem_ctx, const char *, str_list_length(list)+1);
+       if (ret == NULL) return NULL;
+
+       for (i=0;list && list[i];i++) {
+               ret[i] = talloc_strdup(ret, list[i]);
+               if (ret[i] == NULL) {
+                       talloc_free(ret);
+                       return NULL;
+               }
        }
-       
-       *dest = list;
-       return True;    
+       ret[i] = NULL;
+       return ret;
 }
 
-/**
+/*
    Return true if all the elements of the list match exactly.
- **/
-BOOL str_list_compare(char **list1, char **list2)
+ */
+BOOL str_list_equal(const char **list1, const char **list2)
 {
-       int num;
+       int i;
        
-       if (!list1 || !list2)
+       if (list1 == NULL || list2 == NULL) {
                return (list1 == list2); 
+       }
        
-       for (num = 0; list1[num]; num++) {
-               if (!list2[num])
-                       return False;
-               if (!strcsequal(list1[num], list2[num]))
+       for (i=0;list1[i] && list2[i];i++) {
+               if (strcmp(list1[i], list2[i]) != 0) {
                        return False;
+               }
        }
-       if (list2[num])
-               return False; /* if list2 has more elements than list1 fail */
-       
-       return True;
-}
-
-void str_list_free(char ***list)
-{
-       char **tlist;
-       
-       if (!list || !*list)
-               return;
-       tlist = *list;
-       for(; *tlist; tlist++)
-               SAFE_FREE(*tlist);
-       SAFE_FREE(*list);
-}
-
-BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
-{
-       char *p, *s, *t;
-       ssize_t ls, lp, li, ld, i, d;
-
-       if (!list)
-               return False;
-       if (!pattern)
-               return False;
-       if (!insert)
+       if (list1[i] || list2[i]) {
                return False;
-
-       lp = (ssize_t)strlen(pattern);
-       li = (ssize_t)strlen(insert);
-       ld = li -lp;
-                       
-       while (*list) {
-               s = *list;
-               ls = (ssize_t)strlen(s);
-
-               while ((p = strstr(s, pattern))) {
-                       t = *list;
-                       d = p -t;
-                       if (ld) {
-                               t = (char *) malloc(ls +ld +1);
-                               if (!t) {
-                                       DEBUG(0,("str_list_substitute: Unable to allocate memory"));
-                                       return False;
-                               }
-                               memcpy(t, *list, d);
-                               memcpy(t +d +li, p +lp, ls -d -lp +1);
-                               SAFE_FREE(*list);
-                               *list = t;
-                               ls += ld;
-                               s = t +d +li;
-                       }
-                       
-                       for (i = 0; i < li; i++) {
-                               switch (insert[i]) {
-                                       case '`':
-                                       case '"':
-                                       case '\'':
-                                       case ';':
-                                       case '$':
-                                       case '%':
-                                       case '\r':
-                                       case '\n':
-                                               t[d +i] = '_';
-                                               break;
-                                       default:
-                                               t[d +i] = insert[i];
-                               }
-                       }       
-               }
-               
-               list++;
        }
-       
        return True;
 }
 
 
-#define IPSTR_LIST_SEP ","
+/*
+  add an entry to a string list
+*/
+const char **str_list_add(const char **list, const char *s)
+{
+       size_t len = str_list_length(list);
+       const char **ret;
 
-/**
- * Add ip string representation to ipstr list. Used also
- * as part of @function ipstr_list_make
- *
- * @param ipstr_list pointer to string containing ip list;
- *        MUST BE already allocated and IS reallocated if necessary
- * @param ipstr_size pointer to current size of ipstr_list (might be changed
- *        as a result of reallocation)
- * @param ip IP address which is to be added to list
- * @return pointer to string appended with new ip and possibly
- *         reallocated to new length
- **/
+       ret = talloc_realloc(NULL, list, const char *, len+2);
+       if (ret == NULL) return NULL;
 
-char* ipstr_list_add(char** ipstr_list, const struct ipv4_addr *ip)
-{
-       char* new_ipstr = NULL;
-       
-       /* arguments checking */
-       if (!ipstr_list || !ip) return NULL;
+       ret[len] = talloc_strdup(ret, s);
+       if (ret[len] == NULL) return NULL;
 
-       /* attempt to convert ip to a string and append colon separator to it */
-       if (*ipstr_list) {
-               asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,sys_inet_ntoa(*ip));
-               SAFE_FREE(*ipstr_list);
-       } else {
-               asprintf(&new_ipstr, "%s", sys_inet_ntoa(*ip));
-       }
-       *ipstr_list = new_ipstr;
-       return *ipstr_list;
+       ret[len+1] = NULL;
+
+       return ret;
 }
 
-/**
- * Allocate and initialise an ipstr list using ip adresses
- * passed as arguments.
- *
- * @param ipstr_list pointer to string meant to be allocated and set
- * @param ip_list array of ip addresses to place in the list
- * @param ip_count number of addresses stored in ip_list
- * @return pointer to allocated ip string
- **/
-char* ipstr_list_make(char** ipstr_list, const struct ipv4_addr* ip_list, int ip_count)
+/*
+  remove an entry from a string list
+*/
+void str_list_remove(const char **list, const char *s)
 {
        int i;
-       
-       /* arguments checking */
-       if (!ip_list && !ipstr_list) return 0;
 
-       *ipstr_list = NULL;
-       
-       /* process ip addresses given as arguments */
-       for (i = 0; i < ip_count; i++)
-               *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
-       
-       return (*ipstr_list);
+       for (i=0;list[i];i++) {
+               if (strcmp(list[i], s) == 0) break;
+       }
+       if (!list[i]) return;
+
+       for (;list[i];i++) {
+               list[i] = list[i+1];
+       }
 }
 
 
-/**
- * Parse given ip string list into array of ip addresses
- * (as in_addr structures)
- *
- * @param ipstr ip string list to be parsed 
- * @param ip_list pointer to array of ip addresses which is
- *        allocated by this function and must be freed by caller
- * @return number of succesfully parsed addresses
- **/
-int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list)
+/*
+  return True if a string is in a list
+*/
+BOOL str_list_check(const char **list, const char *s)
 {
-       fstring token_str;
-       int count;
-
-       if (!ipstr_list || !ip_list) return 0;
-       
-       for (*ip_list = NULL, count = 0;
-            next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
-            count++) {
-            
-               struct ipv4_addr addr;
+       int i;
 
-               /* convert single token to ip address */
-               if ( (addr.addr = sys_inet_addr(token_str)) == INADDR_NONE )
-                       break;
-               
-               /* prepare place for another in_addr structure */
-               *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct ipv4_addr));
-               if (!*ip_list) return -1;
-               
-               (*ip_list)[count] = addr;
+       for (i=0;list[i];i++) {
+               if (strcmp(list[i], s) == 0) return True;
        }
-       
-       return count;
+       return False;
 }
 
-
-/**
- * Safely free ip string list
- *
- * @param ipstr_list ip string list to be freed
- **/
-
-void ipstr_list_free(char* ipstr_list)
+/*
+  return True if a string is in a list, case insensitively
+*/
+BOOL str_list_check_ci(const char **list, const char *s)
 {
-       SAFE_FREE(ipstr_list);
+       int i;
+
+       for (i=0;list[i];i++) {
+               if (strcasecmp(list[i], s) == 0) return True;
+       }
+       return False;
 }