diff options
Diffstat (limited to 'pith/list.c')
-rw-r--r-- | pith/list.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/pith/list.c b/pith/list.c new file mode 100644 index 00000000..a862260a --- /dev/null +++ b/pith/list.c @@ -0,0 +1,188 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: list.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $"; +#endif + +/* + * ======================================================================== + * Copyright 2006-2007 University of Washington + * Copyright 2013 Eduardo Chappa + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * ======================================================================== + */ + +/*====================================================================== + list.c + ====*/ + + +#include "../pith/headers.h" +#include "../pith/list.h" +#include "../pith/string.h" + + +/* + * Internal prototypes + */ + + +/* + * parse_list - takes a comma delimited list of "count" elements and + * returns an array of pointers to each element neatly + * malloc'd in its own array. Any errors are returned + * in the string pointed to by "error" + * + * If remove_surrounding_double_quotes is set, then double quotes around + * each element of the list are removed. We can't do this for all list + * variables. For example, incoming folders look like + * nickname foldername + * in the config file. Each of those may be quoted separately. + * + * NOTE: only recognizes escaped quotes + */ +char ** +parse_list(char *list, int count, int flags, char **error) +{ + char **lvalue, *p2, *p3, *p4; + int was_quoted = 0; + int remove_surrounding_double_quotes; + int commas_may_be_escaped; + + remove_surrounding_double_quotes = (flags & PL_REMSURRQUOT); + commas_may_be_escaped = (flags & PL_COMMAQUOTE); + + lvalue = (char **) fs_get((count+1) * sizeof(char *)); + count = 0; + while(*list){ /* pick elements from list */ + p2 = list; /* find end of element */ + while(1){ + if(*p2 == '"') /* ignore ',' if quoted */ + was_quoted = (was_quoted) ? 0 : 1 ; + + if(*p2 == '\\' && *(p2+1) == '"') + p2++; /* preserve escaped quotes, too */ + + if((*p2 == ',' && !was_quoted) || *p2 == '\0') + break; + + if(commas_may_be_escaped && *p2 == '\\' && *(p2+1) == ',') + p2++; + + p2++; + } + + if(was_quoted){ /* unbalanced quotes! */ + if(error) + *error = "Unbalanced quotes"; + + break; + } + + /* + * if element found, eliminate trailing + * white space and tie into variable list + */ + if(p2 != list){ + for(p3 = p2 - 1; isspace((unsigned char) *p3) && list < p3; p3--) + ; + + p4 = fs_get(((p3 - list) + 2) * sizeof(char)); + lvalue[count] = p4; + while(list <= p3) + *p4++ = *list++; + + *p4 = '\0'; + + if(remove_surrounding_double_quotes) + removing_double_quotes(lvalue[count]); + + count++; + } + + if(*(list = p2) != '\0'){ /* move to beginning of next val */ + while(*list == ',' || isspace((unsigned char)*list)) + list++; + } + } + + lvalue[count] = NULL; /* tie off pointer list */ + return(lvalue); +} + + +/* + * Free array of string pointers and associated strings + * + * Args: list -- array of char *'s + */ +void +free_list_array(char ***list) +{ + char **p; + + if(list && *list){ + for(p = *list; *p; p++) + fs_give((void **) p); + + fs_give((void **) list); + } +} + + +/* + * Copy array of string pointers and associated strings + * + * Args: list -- array of char *'s + * + * Returns: Allocated array of string pointers and allocated copies of strings. + * Caller should free the list array when done. + */ +char ** +copy_list_array(char **list) +{ + int i, cnt = 0; + char **p, **ret_list = NULL; + + if(list){ + while(list[cnt++]) + ; + + p = ret_list = (char **)fs_get((cnt+1) * sizeof(char *)); + memset((void *) ret_list, 0, (cnt+1) * sizeof(char *)); + + for(i=0; list[i]; i++, p++) + *p = cpystr(list[i]); + + *p = NULL; + + } + + return(ret_list); +} + + +int +equal_list_arrays(char **list1, char **list2) +{ + int ret = 0; + + if(list1 && list2){ + while(*list1){ + if(!*list2 || strcmp(*list1, *list2) != 0) + break; + + list1++; + list2++; + } + + if(*list1 == NULL && *list2 == NULL) + ret++; + } + + return(ret); +} |