aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/pqexpbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/libpq/pqexpbuffer.c')
-rw-r--r--src/interfaces/libpq/pqexpbuffer.c103
1 files changed, 73 insertions, 30 deletions
diff --git a/src/interfaces/libpq/pqexpbuffer.c b/src/interfaces/libpq/pqexpbuffer.c
index ddaca7e67b5..bedf456b3ce 100644
--- a/src/interfaces/libpq/pqexpbuffer.c
+++ b/src/interfaces/libpq/pqexpbuffer.c
@@ -8,11 +8,15 @@
*
* This module is essentially the same as the backend's StringInfo data type,
* but it is intended for use in frontend libpq and client applications.
- * Thus, it does not rely on palloc(), elog(), nor vsnprintf().
+ * Thus, it does not rely on palloc() nor elog().
+ *
+ * It does rely on vsnprintf(); if configure finds that libc doesn't provide
+ * a usable vsnprintf(), then a copy of our own implementation of it will
+ * be linked into libpq.
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.1 1999/08/31 01:37:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.2 2000/01/17 02:59:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -148,27 +152,47 @@ enlargePQExpBuffer(PQExpBuffer str, int needed)
* and insert it into str. More space is allocated to str if necessary.
* This is a convenience routine that does the same thing as
* resetPQExpBuffer() followed by appendPQExpBuffer().
- *
- * CAUTION: the frontend version of this routine WILL FAIL if the result of
- * the sprintf formatting operation exceeds 1KB of data (but the size of the
- * pre-existing string in the buffer doesn't matter). We could make it
- * support larger strings, but that requires vsnprintf() which is not
- * universally available. Currently there is no need for long strings to be
- * formatted in the frontend. We could support it, if necessary, by
- * conditionally including a vsnprintf emulation.
*/
void
printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
- char buffer[1024];
-
- va_start(args, fmt);
- vsprintf(buffer, fmt, args);
- va_end(args);
+ int avail,
+ nprinted;
resetPQExpBuffer(str);
- appendPQExpBufferStr(str, buffer);
+
+ for (;;)
+ {
+ /*----------
+ * Try to format the given string into the available space;
+ * but if there's hardly any space, don't bother trying,
+ * just fall through to enlarge the buffer first.
+ *----------
+ */
+ avail = str->maxlen - str->len - 1;
+ if (avail > 16)
+ {
+ va_start(args, fmt);
+ nprinted = vsnprintf(str->data + str->len, avail,
+ fmt, args);
+ va_end(args);
+ /*
+ * Note: some versions of vsnprintf return the number of chars
+ * actually stored, but at least one returns -1 on failure.
+ * Be conservative about believing whether the print worked.
+ */
+ if (nprinted >= 0 && nprinted < avail-1)
+ {
+ /* Success. Note nprinted does not include trailing null. */
+ str->len += nprinted;
+ break;
+ }
+ }
+ /* Double the buffer size and try again. */
+ if (! enlargePQExpBuffer(str, str->maxlen))
+ return; /* oops, out of memory */
+ }
}
/*------------------------
@@ -178,26 +202,45 @@ printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
* and append it to whatever is already in str. More space is allocated
* to str if necessary. This is sort of like a combination of sprintf and
* strcat.
- *
- * CAUTION: the frontend version of this routine WILL FAIL if the result of
- * the sprintf formatting operation exceeds 1KB of data (but the size of the
- * pre-existing string in the buffer doesn't matter). We could make it
- * support larger strings, but that requires vsnprintf() which is not
- * universally available. Currently there is no need for long strings to be
- * formatted in the frontend. We could support it, if necessary, by
- * conditionally including a vsnprintf emulation.
*/
void
appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{
va_list args;
- char buffer[1024];
-
- va_start(args, fmt);
- vsprintf(buffer, fmt, args);
- va_end(args);
+ int avail,
+ nprinted;
- appendPQExpBufferStr(str, buffer);
+ for (;;)
+ {
+ /*----------
+ * Try to format the given string into the available space;
+ * but if there's hardly any space, don't bother trying,
+ * just fall through to enlarge the buffer first.
+ *----------
+ */
+ avail = str->maxlen - str->len - 1;
+ if (avail > 16)
+ {
+ va_start(args, fmt);
+ nprinted = vsnprintf(str->data + str->len, avail,
+ fmt, args);
+ va_end(args);
+ /*
+ * Note: some versions of vsnprintf return the number of chars
+ * actually stored, but at least one returns -1 on failure.
+ * Be conservative about believing whether the print worked.
+ */
+ if (nprinted >= 0 && nprinted < avail-1)
+ {
+ /* Success. Note nprinted does not include trailing null. */
+ str->len += nprinted;
+ break;
+ }
+ }
+ /* Double the buffer size and try again. */
+ if (! enlargePQExpBuffer(str, str->maxlen))
+ return; /* oops, out of memory */
+ }
}
/*------------------------