MINOR: tools: make csv_enc_append() always start at the first byte of the chunk

csv_enc_append() returns a pointer to the beginning of the encoded
string, which makes it convenient to use in printf(). However it's not
convenient for use in chunks as it may leave an unused byte at the
beginning depending on the automatic quoting. Let's modify it to work
in two passes. First it looks for a character that requires escaping
using strpbrk(), and second it encodes the string. This way it
guarantees to always start at the first available byte of the chunk.
Additionally it made the code quite simpler.
This commit is contained in:
Willy Tarreau 2016-01-08 10:04:08 +01:00
parent 898529b4a8
commit b631c291c9

View File

@ -1443,8 +1443,8 @@ char *encode_chunk(char *start, char *stop,
* *
* printf("..., \"%s\", ...\r\n", csv_enc(str, 0, &trash)); * printf("..., \"%s\", ...\r\n", csv_enc(str, 0, &trash));
* *
* If <quote> is 1, the converter puts the quotes only if any character is * If <quote> is 1, the converter puts the quotes only if any reserved character
* escaped. If <quote> is 2, the converter always puts the quotes. * is present. If <quote> is 2, the converter always puts the quotes.
* *
* <output> is a struct chunk used for storing the output string. * <output> is a struct chunk used for storing the output string.
* *
@ -1455,20 +1455,29 @@ char *encode_chunk(char *start, char *stop,
* If the output buffer is too short to contain the input string, the result * If the output buffer is too short to contain the input string, the result
* is truncated. * is truncated.
* *
* This function appends the encoding to the existing output chunk. Please * This function appends the encoding to the existing output chunk, and it
* use csv_enc() instead if you want to replace the output chunk. * guarantees that it starts immediately at the first available character of
* the chunk. Please use csv_enc() instead if you want to replace the output
* chunk.
*/ */
const char *csv_enc_append(const char *str, int quote, struct chunk *output) const char *csv_enc_append(const char *str, int quote, struct chunk *output)
{ {
char *end = output->str + output->size; char *end = output->str + output->size;
char *out = output->str + output->len + 1; /* +1 for reserving space for a first <"> */ char *out = output->str + output->len;
char *ptr = out; char *ptr = out;
if (quote == 1) {
/* automatic quoting: first verify if we'll have to quote the string */
if (!strpbrk(str, "\n\r,\""))
quote = 0;
}
if (quote)
*ptr++ = '"';
while (*str && ptr < end - 2) { /* -2 for reserving space for <"> and \0. */ while (*str && ptr < end - 2) { /* -2 for reserving space for <"> and \0. */
*ptr = *str; *ptr = *str;
if (*str == '"') { if (*str == '"') {
if (quote == 1)
quote = 2;
ptr++; ptr++;
if (ptr >= end - 2) { if (ptr >= end - 2) {
ptr--; ptr--;
@ -1476,21 +1485,13 @@ const char *csv_enc_append(const char *str, int quote, struct chunk *output)
} }
*ptr = '"'; *ptr = '"';
} }
if (quote == 1 && ( *str == '\r' || *str == '\n' || *str == ',') )
quote = 2;
ptr++; ptr++;
str++; str++;
} }
if (quote < 2) { if (quote)
*ptr = '\0'; *ptr++ = '"';
output->len = ptr - output->str;
return out;
}
/* quote == 2 : add quotes */
*--out = '"';
*++ptr = '"';
*ptr = '\0'; *ptr = '\0';
output->len = ptr - output->str; output->len = ptr - output->str;
return out; return out;