#include "postgres_fe.h"
#include <ctype.h>
#include "common.h"
#include "stringutils.h"
Go to the source code of this file.
Functions | |
char * | strtokx (const char *s, const char *whitespace, const char *delim, const char *quote, char escape, bool e_strings, bool del_quotes, int encoding) |
void | strip_quotes (char *source, char quote, char escape, int encoding) |
char * | quote_if_needed (const char *source, const char *entails_quote, char quote, char escape, int encoding) |
char* quote_if_needed | ( | const char * | source, | |
const char * | entails_quote, | |||
char | quote, | |||
char | escape, | |||
int | encoding | |||
) |
Definition at line 291 of file stringutils.c.
References Assert, free, i, NULL, pg_malloc(), and PQmblen().
{ const char *src; char *ret; char *dst; bool need_quotes = false; Assert(source != NULL); Assert(quote != '\0'); src = source; dst = ret = pg_malloc(2 * strlen(src) + 3); /* excess */ *dst++ = quote; while (*src) { char c = *src; int i; if (c == quote) { need_quotes = true; *dst++ = quote; } else if (c == escape) { need_quotes = true; *dst++ = escape; } else if (strchr(entails_quote, c)) need_quotes = true; i = PQmblen(src, encoding); while (i--) *dst++ = *src++; } *dst++ = quote; *dst = '\0'; if (!need_quotes) { free(ret); ret = NULL; } return ret; }
void strip_quotes | ( | char * | source, | |
char | quote, | |||
char | escape, | |||
int | encoding | |||
) |
Definition at line 240 of file stringutils.c.
References Assert, i, NULL, and PQmblen().
Referenced by parse_slash_copy(), and strtokx().
{ char *src; char *dst; Assert(source != NULL); Assert(quote != '\0'); src = dst = source; if (*src && *src == quote) src++; /* skip leading quote */ while (*src) { char c = *src; int i; if (c == quote && src[1] == '\0') break; /* skip trailing quote */ else if (c == quote && src[1] == quote) src++; /* process doubled quote */ else if (c == escape && src[1] != '\0') src++; /* process escaped character */ i = PQmblen(src, encoding); while (i--) *dst++ = *src++; } *dst = '\0'; }
char* strtokx | ( | const char * | s, | |
const char * | whitespace, | |||
const char * | delim, | |||
const char * | quote, | |||
char | escape, | |||
bool | e_strings, | |||
bool | del_quotes, | |||
int | encoding | |||
) |
Definition at line 52 of file stringutils.c.
References free, memmove, pg_malloc(), PQmblen(), and strip_quotes().
Referenced by parse_slash_copy().
{ 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 *p; if (s) { free(storage); /* * We may need extra space to insert delimiter nulls for adjacent * tokens. 2X the space is a gross overestimate, but it's unlikely * that this code will be used on huge strings anyway. */ storage = pg_malloc(2 * strlen(s) + 1); strcpy(storage, s); string = storage; } if (!storage) return NULL; /* skip leading whitespace */ offset = strspn(string, whitespace); start = &string[offset]; /* end of string reached? */ if (*start == '\0') { /* technically we don't need to free here, but we're nice */ free(storage); storage = NULL; string = NULL; return NULL; } /* test if delimiter character */ if (delim && strchr(delim, *start)) { /* * If not at end of string, we need to insert a null to terminate the * returned token. We can just overwrite the next character if it * happens to be in the whitespace set ... otherwise move over the * rest of the string to make room. (This is why we allocated extra * space above). */ p = start + 1; if (*p != '\0') { if (!strchr(whitespace, *p)) memmove(p + 1, p, strlen(p) + 1); *p = '\0'; string = p + 1; } else { /* at end of string, so no extra work */ string = p; } return start; } /* check for E string */ p = start; if (e_strings && (*p == 'E' || *p == 'e') && p[1] == '\'') { quote = "'"; escape = '\\'; /* if std strings before, not any more */ p++; } /* test if quoting character */ if (quote && strchr(quote, *p)) { /* okay, we have a quoted token, now scan for the closer */ char thisquote = *p++; for (; *p; p += PQmblen(p, encoding)) { if (*p == escape && p[1] != '\0') p++; /* process escaped anything */ else if (*p == thisquote && p[1] == thisquote) p++; /* process doubled quote */ else if (*p == thisquote) { p++; /* skip trailing quote */ break; } } /* * If not at end of string, we need to insert a null to terminate the * returned token. See notes above. */ if (*p != '\0') { if (!strchr(whitespace, *p)) memmove(p + 1, p, strlen(p) + 1); *p = '\0'; string = p + 1; } else { /* at end of string, so no extra work */ string = p; } /* Clean up the token if caller wants that */ if (del_quotes) strip_quotes(start, thisquote, escape, encoding); return start; } /* * Otherwise no quoting character. Scan till next whitespace, delimiter * or quote. NB: at this point, *start is known not to be '\0', * whitespace, delim, or quote, so we will consume at least one character. */ offset = strcspn(start, whitespace); if (delim) { unsigned int offset2 = strcspn(start, delim); if (offset > offset2) offset = offset2; } if (quote) { unsigned int offset2 = strcspn(start, quote); if (offset > offset2) offset = offset2; } p = start + offset; /* * If not at end of string, we need to insert a null to terminate the * returned token. See notes above. */ if (*p != '\0') { if (!strchr(whitespace, *p)) memmove(p + 1, p, strlen(p) + 1); *p = '\0'; string = p + 1; } else { /* at end of string, so no extra work */ string = p; } return start; }