diff options
author | Bruce Momjian <bruce@momjian.us> | 1999-11-04 21:56:02 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1999-11-04 21:56:02 +0000 |
commit | a45195a191eec367a4f305bb71ab541d17a3b9f9 (patch) | |
tree | 99b815a93f6175b0db76c2da0da39e95a0ee6b8d /src/bin/psql/stringutils.c | |
parent | 2ea3b6d63addeaf07267e2390597645cbf013c36 (diff) | |
download | postgresql-a45195a191eec367a4f305bb71ab541d17a3b9f9.tar.gz postgresql-a45195a191eec367a4f305bb71ab541d17a3b9f9.zip |
Major psql overhaul by Peter Eisentraut.
Diffstat (limited to 'src/bin/psql/stringutils.c')
-rw-r--r-- | src/bin/psql/stringutils.c | 254 |
1 files changed, 157 insertions, 97 deletions
diff --git a/src/bin/psql/stringutils.c b/src/bin/psql/stringutils.c index f3cedd39a68..c495fd49660 100644 --- a/src/bin/psql/stringutils.c +++ b/src/bin/psql/stringutils.c @@ -1,119 +1,179 @@ -/*------------------------------------------------------------------------- - * - * stringutils.c - * simple string manipulation routines - * - * Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/psql/stringutils.c,v 1.17 1999/07/17 20:18:24 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include <ctype.h> +#include <config.h> +#include <c.h> +#include "stringutils.h" + +//#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +//#include <stdio.h> -#include "postgres.h" +#include <postgres.h> #ifndef HAVE_STRDUP -#include "strdup.h" +#include <strdup.h> #endif +#include <libpq-fe.h> + -#include "stringutils.h" -/* all routines assume null-terminated strings! */ +static void +unescape_quotes(char *source, char quote, char escape); -/* The following routines remove whitespaces from the left, right - and both sides of a string */ -/* MODIFIES the string passed in and returns the head of it */ -#ifdef NOT_USED -static char * -leftTrim(char *s) +/* + * Replacement for strtok() (a.k.a. poor man's flex) + * + * The calling convention is similar to that of strtok. + * s - string to parse, if NULL continue parsing the last string + * delim - set of characters that delimit tokens (usually whitespace) + * quote - set of characters that quote stuff, they're not part of the token + * escape - character than can quote quotes + * was_quoted - if not NULL, stores the quoting character if any was encountered + * token_pos - if not NULL, receives a count to the start of the token in the + * parsed string + * + * Note that the string s is _not_ overwritten in this implementation. + */ +char * strtokx(const char *s, + const char *delim, + const char *quote, + char escape, + char * was_quoted, + unsigned int * token_pos) { - char *s2 = s; - int shift = 0; - int j = 0; - - while (isspace(*s)) - { - s++; - shift++; + static char * storage = NULL; /* store the local copy of the users string here */ + static char * string = NULL; /* pointer into storage where to continue on next call */ + /* variously abused variables: */ + unsigned int offset; + char * start; + char *cp = NULL; + + if (s) { + free(storage); + storage = strdup(s); + string = storage; + } + + if (!storage) + return NULL; + + /* skip leading "whitespace" */ + offset = strspn(string, delim); + + /* end of string reached */ + if (string[offset] == '\0') { + /* technically we don't need to free here, but we're nice */ + free(storage); + storage = NULL; + string = NULL; + return NULL; + } + + /* test if quoting character */ + if (quote) + cp = strchr(quote, string[offset]); + + if (cp) { + /* okay, we have a quoting character, now scan for the closer */ + char *p; + start = &string[offset+1]; + + if (token_pos) + *token_pos = start - storage; + + for(p = start; + *p && (*p != *cp || *(p-1) == escape) ; +#ifdef MULTIBYTE + p += PQmblen(p) +#else + p++ +#endif + ); + + /* not yet end of string? */ + if (*p != '\0') { + *p = '\0'; + string = p + 1; + if (was_quoted) + *was_quoted = *cp; + unescape_quotes (start, *cp, escape); + return start; } - if (shift > 0) - { - while ((s2[j] = s2[j + shift]) != '\0') - j++; + else { + if (was_quoted) + *was_quoted = *cp; + string = p; + + unescape_quotes (start, *cp, escape); + return start; } + } - return s2; -} + /* otherwise no quoting character. scan till next delimiter */ + start = &string[offset]; -#endif + if (token_pos) + *token_pos = start - storage; -char * -rightTrim(char *s) -{ - char *sEnd, - *bsEnd; - bool in_bs = false; - - sEnd = s + strlen(s) - 1; - while (sEnd >= s && isspace(*sEnd)) - sEnd--; - bsEnd = sEnd; - while (bsEnd >= s && *bsEnd == '\\') - { - in_bs = (in_bs == false); - bsEnd--; - } - if (in_bs && *sEnd) - sEnd++; - if (sEnd < s) - s[0] = '\0'; - else - s[sEnd - s + 1] = '\0'; - return s; + offset = strcspn(start, delim); + if (was_quoted) + *was_quoted = 0; + + if (start[offset] != '\0') { + start[offset] = '\0'; + string = &start[offset]+1; + + return start; + } + else { + string = &start[offset]; + return start; + } } -#ifdef NOT_USED -static char * -doubleTrim(char *s) + + + +/* + * unescape_quotes + * + * Resolves escaped quotes. Used by strtokx above. + */ +static void +unescape_quotes(char *source, char quote, char escape) { - strcpy(s, leftTrim(rightTrim(s))); - return s; -} + char *p; + char *destination, *tmp; +#ifdef USE_ASSERT_CHECKING + assert(source); #endif -#ifdef STRINGUTILS_TEST -void -testStringUtils() -{ - static char *tests[] = {" goodbye \n", /* space on both ends */ - "hello world", /* no spaces to trim */ - "", /* empty string */ - "a", /* string with one char */ - " ", /* string with one whitespace */ - NULL_STR}; - - int i = 0; - - while (tests[i] != NULL_STR) - { - char *t; - - t = strdup(tests[i]); - printf("leftTrim(%s) = ", t); - printf("%sEND\n", leftTrim(t)); - t = strdup(tests[i]); - printf("rightTrim(%s) = ", t); - printf("%sEND\n", rightTrim(t)); - t = strdup(tests[i]); - printf("doubleTrim(%s) = ", t); - printf("%sEND\n", doubleTrim(t)); - i++; + destination = (char *) calloc(1, strlen(source)+1); + if (!destination) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + tmp = destination; + + for (p = source; *p; p++) + { + char c; + + if (*p == escape && *(p+1) && quote == *(p+1)) { + c = *(p+1); + p++; } + else + c = *p; -} + *tmp = c; + tmp ++; + } -#endif + /* Terminating null character */ + *tmp = '\0'; + + strcpy(source, destination); +} |