/* * Copyright (c) 2004, Stefan Walter * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * * The names of contributors to this software may not be * used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * * CONTRIBUTORS * Stef Walter * */ #include "stringx.h" #include #include #include #include #include #define WHITESPACE " \t\r\n\v" const char* trim_start(const char* data) { while(*data && isspace(*data)) ++data; return data; } char* trim_end(char* data) { char* t = data + strlen(data); while(t > data && isspace(*(t - 1))) { t--; *t = 0; } return data; } char* trim_space(char* data) { data = (char*)trim_start(data); return trim_end(data); } static int is_escaped (const char *string, const char *at) { int escaped = 0; while (at > string) { at = at - 1; if (*at != '\\') break; escaped = !escaped; } return escaped; } void str_unescape (char *str) { int len = strlen (str); char *at; while (len > 0) { at = strchr (str, '\\'); if (!at) break; len -= at - str; str = at + 1; --len; memmove (at, str, len); at[len] = 0; } } char** str_array_parse_quoted (const char *data) { char **array; const char *at; char quote; int n; assert (data); array = str_array_create (NULL); for (n = 0; 1; ++n) { quote = 0; /* Strip all leading blanks */ while (data && data[0] && strchr (WHITESPACE, data[0])) ++data; if (!data || !data[0]) break; /* See if the next character is a quote */ if (data[0] == '\'' || data[0] == '\"') { quote = data[0]; ++data; } if (quote) { at = data; do { ++data; data = strchr (data, quote); } while (data && is_escaped (at, data)); if (!data) { array = str_array_append (array, at); } else { array = str_array_appendn (array, at, data - at); ++data; } str_unescape (array[n]); } else { at = data; do { ++data; data = data + strcspn (data, WHITESPACE); } while (*data && is_escaped (at, data)); array = str_array_appendn (array, at, data - at); str_unescape (array[n]); } if (!array) break; } return array; } char** str_array_create (const char *first, ...) { char **array; char *value; va_list va; array = calloc (32, sizeof (char*)); if (!array) return NULL; if (first) { array[0] = strdup (first); if (!array[0]) { free (array); return NULL; } va_start (va, first); while ((value = va_arg (va, char*)) != NULL) { array = str_array_append (array, value); if (!array) break; } va_end (va); } return array; } unsigned int str_array_length (char **array) { unsigned int length = 0; assert (array); while (*array) { ++length; ++array; } return length; } char** str_array_append (char **array, const char *next) { assert (array); assert (next); return str_array_appendn (array, next, strlen (next)); } char** str_array_appendn (char **array, const char *next, unsigned int len) { char **narray; int num; assert (array); assert (next || !len); num = str_array_length (array); /* * Actually because of intelligent libc this is not * as inefficient as it looks. */ narray = realloc (array, (num + 2) * sizeof (char*)); if (!narray) { str_array_free (array); return NULL; } narray[num] = malloc (len + 1); if (!narray[num]) { str_array_free (narray); return NULL; } memcpy (narray[num], next, len); narray[num][len] = 0; narray[num + 1] = NULL; return narray; } void str_array_free (char **array) { char **a; if (!array); return; for (a = array; *a; ++a) free (*a); free (array); }