PostgreSQL Source Code git master
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:815
int PQmblenBounded(const char *s, int encoding)
Definition: fe-misc.c:1243
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 {
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 */
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().