aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/stringutils.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1999-11-04 21:56:02 +0000
committerBruce Momjian <bruce@momjian.us>1999-11-04 21:56:02 +0000
commita45195a191eec367a4f305bb71ab541d17a3b9f9 (patch)
tree99b815a93f6175b0db76c2da0da39e95a0ee6b8d /src/bin/psql/stringutils.c
parent2ea3b6d63addeaf07267e2390597645cbf013c36 (diff)
downloadpostgresql-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.c254
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);
+}