PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
stringutils.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include "common.h"
#include "stringutils.h"
Include dependency graph for stringutils.c:

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, bool force_quote, int encoding)
 

Function Documentation

◆ quote_if_needed()

char* quote_if_needed ( const char *  source,
const char *  entails_quote,
char  quote,
char  escape,
bool  force_quote,
int  encoding 
)

Definition at line 292 of file stringutils.c.

295 {
296  const char *src;
297  char *ret;
298  char *dst;
299  bool need_quotes = force_quote;
300 
301  Assert(source != NULL);
302  Assert(quote != '\0');
303 
304  src = source;
305  dst = ret = pg_malloc(2 * strlen(src) + 3); /* excess */
306 
307  *dst++ = quote;
308 
309  while (*src)
310  {
311  char c = *src;
312  int i;
313 
314  if (c == quote)
315  {
316  need_quotes = true;
317  *dst++ = quote;
318  }
319  else if (c == escape)
320  {
321  need_quotes = true;
322  *dst++ = escape;
323  }
324  else if (strchr(entails_quote, c))
325  need_quotes = true;
326 
327  i = PQmblenBounded(src, encoding);
328  while (i--)
329  *dst++ = *src++;
330  }
331 
332  *dst++ = quote;
333  *dst = '\0';
334 
335  if (!need_quotes)
336  {
337  free(ret);
338  ret = NULL;
339  }
340 
341  return ret;
342 }
#define Assert(condition)
Definition: c.h:863
int PQmblenBounded(const char *s, int encoding)
Definition: fe-misc.c:1234
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define free(a)
Definition: header.h:65
int i
Definition: isn.c:72
int32 encoding
Definition: pg_database.h:41
static rewind_source * source
Definition: pg_rewind.c:89
char * c

References Assert, encoding, free, i, pg_malloc(), PQmblenBounded(), and source.

◆ strip_quotes()

void strip_quotes ( char *  source,
char  quote,
char  escape,
int  encoding 
)

Definition at line 240 of file stringutils.c.

241 {
242  char *src;
243  char *dst;
244 
245  Assert(source != NULL);
246  Assert(quote != '\0');
247 
248  src = dst = source;
249 
250  if (*src && *src == quote)
251  src++; /* skip leading quote */
252 
253  while (*src)
254  {
255  char c = *src;
256  int i;
257 
258  if (c == quote && src[1] == '\0')
259  break; /* skip trailing quote */
260  else if (c == quote && src[1] == quote)
261  src++; /* process doubled quote */
262  else if (c == escape && src[1] != '\0')
263  src++; /* process escaped character */
264 
265  i = PQmblenBounded(src, encoding);
266  while (i--)
267  *dst++ = *src++;
268  }
269 
270  *dst = '\0';
271 }

References Assert, encoding, i, PQmblenBounded(), and source.

Referenced by parse_slash_copy(), and strtokx().

◆ strtokx()

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.

60 {
61  static char *storage = NULL; /* store the local copy of the users
62  * string here */
63  static char *string = NULL; /* pointer into storage where to continue on
64  * next call */
65 
66  /* variously abused variables: */
67  unsigned int offset;
68  char *start;
69  char *p;
70 
71  if (s)
72  {
73  free(storage);
74 
75  /*
76  * We may need extra space to insert delimiter nulls for adjacent
77  * tokens. 2X the space is a gross overestimate, but it's unlikely
78  * that this code will be used on huge strings anyway.
79  */
80  storage = pg_malloc(2 * strlen(s) + 1);
81  strcpy(storage, s);
82  string = storage;
83  }
84 
85  if (!storage)
86  return NULL;
87 
88  /* skip leading whitespace */
89  offset = strspn(string, whitespace);
90  start = &string[offset];
91 
92  /* end of string reached? */
93  if (*start == '\0')
94  {
95  /* technically we don't need to free here, but we're nice */
96  free(storage);
97  storage = NULL;
98  string = NULL;
99  return NULL;
100  }
101 
102  /* test if delimiter character */
103  if (delim && strchr(delim, *start))
104  {
105  /*
106  * If not at end of string, we need to insert a null to terminate the
107  * returned token. We can just overwrite the next character if it
108  * happens to be in the whitespace set ... otherwise move over the
109  * rest of the string to make room. (This is why we allocated extra
110  * space above).
111  */
112  p = start + 1;
113  if (*p != '\0')
114  {
115  if (!strchr(whitespace, *p))
116  memmove(p + 1, p, strlen(p) + 1);
117  *p = '\0';
118  string = p + 1;
119  }
120  else
121  {
122  /* at end of string, so no extra work */
123  string = p;
124  }
125 
126  return start;
127  }
128 
129  /* check for E string */
130  p = start;
131  if (e_strings &&
132  (*p == 'E' || *p == 'e') &&
133  p[1] == '\'')
134  {
135  quote = "'";
136  escape = '\\'; /* if std strings before, not any more */
137  p++;
138  }
139 
140  /* test if quoting character */
141  if (quote && strchr(quote, *p))
142  {
143  /* okay, we have a quoted token, now scan for the closer */
144  char thisquote = *p++;
145 
146  for (; *p; p += PQmblenBounded(p, encoding))
147  {
148  if (*p == escape && p[1] != '\0')
149  p++; /* process escaped anything */
150  else if (*p == thisquote && p[1] == thisquote)
151  p++; /* process doubled quote */
152  else if (*p == thisquote)
153  {
154  p++; /* skip trailing quote */
155  break;
156  }
157  }
158 
159  /*
160  * If not at end of string, we need to insert a null to terminate the
161  * returned token. See notes above.
162  */
163  if (*p != '\0')
164  {
165  if (!strchr(whitespace, *p))
166  memmove(p + 1, p, strlen(p) + 1);
167  *p = '\0';
168  string = p + 1;
169  }
170  else
171  {
172  /* at end of string, so no extra work */
173  string = p;
174  }
175 
176  /* Clean up the token if caller wants that */
177  if (del_quotes)
178  strip_quotes(start, thisquote, escape, encoding);
179 
180  return start;
181  }
182 
183  /*
184  * Otherwise no quoting character. Scan till next whitespace, delimiter
185  * or quote. NB: at this point, *start is known not to be '\0',
186  * whitespace, delim, or quote, so we will consume at least one character.
187  */
188  offset = strcspn(start, whitespace);
189 
190  if (delim)
191  {
192  unsigned int offset2 = strcspn(start, delim);
193 
194  if (offset > offset2)
195  offset = offset2;
196  }
197 
198  if (quote)
199  {
200  unsigned int offset2 = strcspn(start, quote);
201 
202  if (offset > offset2)
203  offset = offset2;
204  }
205 
206  p = start + offset;
207 
208  /*
209  * If not at end of string, we need to insert a null to terminate the
210  * returned token. See notes above.
211  */
212  if (*p != '\0')
213  {
214  if (!strchr(whitespace, *p))
215  memmove(p + 1, p, strlen(p) + 1);
216  *p = '\0';
217  string = p + 1;
218  }
219  else
220  {
221  /* at end of string, so no extra work */
222  string = p;
223  }
224 
225  return start;
226 }
return str start
#define storage
Definition: indent_codes.h:68
void strip_quotes(char *source, char quote, char escape, int encoding)
Definition: stringutils.c:240

References encoding, free, pg_malloc(), PQmblenBounded(), start, storage, and strip_quotes().

Referenced by parse_slash_copy().