aboutsummaryrefslogtreecommitdiff
path: root/src/backend/lib/stringinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/lib/stringinfo.c')
-rw-r--r--src/backend/lib/stringinfo.c64
1 files changed, 28 insertions, 36 deletions
diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c
index a5b9f2e03e1..016eac4891c 100644
--- a/src/backend/lib/stringinfo.c
+++ b/src/backend/lib/stringinfo.c
@@ -80,18 +80,18 @@ appendStringInfo(StringInfo str, const char *fmt,...)
for (;;)
{
va_list args;
- bool success;
+ int needed;
/* Try to format the data. */
va_start(args, fmt);
- success = appendStringInfoVA(str, fmt, args);
+ needed = appendStringInfoVA(str, fmt, args);
va_end(args);
- if (success)
- break;
+ if (needed == 0)
+ break; /* success */
- /* Double the buffer size and try again. */
- enlargeStringInfo(str, str->maxlen);
+ /* Increase the buffer size and try again. */
+ enlargeStringInfo(str, needed);
}
}
@@ -100,59 +100,51 @@ appendStringInfo(StringInfo str, const char *fmt,...)
*
* Attempt to format text data under the control of fmt (an sprintf-style
* format string) and append it to whatever is already in str. If successful
- * return true; if not (because there's not enough space), return false
- * without modifying str. Typically the caller would enlarge str and retry
- * on false return --- see appendStringInfo for standard usage pattern.
+ * return zero; if not (because there's not enough space), return an estimate
+ * of the space needed, without modifying str. Typically the caller should
+ * pass the return value to enlargeStringInfo() before trying again; see
+ * appendStringInfo for standard usage pattern.
*
* XXX This API is ugly, but there seems no alternative given the C spec's
* restrictions on what can portably be done with va_list arguments: you have
* to redo va_start before you can rescan the argument list, and we can't do
* that from here.
*/
-bool
+int
appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
{
- int avail,
- nprinted;
+ int avail;
+ size_t nprinted;
Assert(str != NULL);
/*
* If there's hardly any space, don't bother trying, just fail to make the
- * caller enlarge the buffer first.
+ * caller enlarge the buffer first. We have to guess at how much to
+ * enlarge, since we're skipping the formatting work.
*/
- avail = str->maxlen - str->len - 1;
+ avail = str->maxlen - str->len;
if (avail < 16)
- return false;
+ return 32;
- /*
- * Assert check here is to catch buggy vsnprintf that overruns the
- * specified buffer length. Solaris 7 in 64-bit mode is an example of a
- * platform with such a bug.
- */
-#ifdef USE_ASSERT_CHECKING
- str->data[str->maxlen - 1] = '\0';
-#endif
-
- nprinted = vsnprintf(str->data + str->len, avail, fmt, args);
+ nprinted = pvsnprintf(str->data + str->len, (size_t) avail, fmt, args);
- Assert(str->data[str->maxlen - 1] == '\0');
-
- /*
- * 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)
+ if (nprinted < (size_t) avail)
{
/* Success. Note nprinted does not include trailing null. */
- str->len += nprinted;
- return true;
+ str->len += (int) nprinted;
+ return 0;
}
/* Restore the trailing null so that str is unmodified. */
str->data[str->len] = '\0';
- return false;
+
+ /*
+ * Return pvsnprintf's estimate of the space needed. (Although this is
+ * given as a size_t, we know it will fit in int because it's not more
+ * than MaxAllocSize.)
+ */
+ return (int) nprinted;
}
/*