PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
stringutils.h File Reference
This graph shows which files directly or indirectly include this file:

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}
int PQmblenBounded(const char *s, int encoding)
Definition: fe-misc.c:1243
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
Assert(PointerIsAligned(start, uint64))
#define free(a)
Definition: header.h:65
int i
Definition: isn.c:74
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().