/*
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 in_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,inet_ntoa(*ip));
- SAFE_FREE(*ipstr_list);
- } else {
- asprintf(&new_ipstr, "%s", 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 in_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 in_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 in_addr addr;
+ int i;
- /* convert single token to ip address */
- if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
- break;
-
- /* prepare place for another in_addr structure */
- *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_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;
}