From 426d6749cf534dec673e958f98711ac64a04f9a6 Mon Sep 17 00:00:00 2001 From: Joost Peters Date: Sun, 10 Oct 2010 22:36:03 +0000 Subject: COMMON: work around different vsnprintf behaviour on IRIX The return value of vsnprintf when the provided buffer is not large enough to hold the formatted string is implementation-dependent: C99: The size the formatted string would take up. MSVC: -1, with no indication of how large the buffer should be. IRIX: The number of characters actually written, which is at most the size of the buffer minus one, as the string is truncated to fit. This means the only way to be sure the entire string is written is if the return value is less than the capacity - 1. This change means that whenever we try to format a string where the size is 1 below the built-in capacity, that the capacity will be needlessly increased. If this turns out to be problematic we could make this behaviour __sgi conditional. svn-id: r53143 --- common/str.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/str.cpp b/common/str.cpp index 4585905d62..c3c19adfe6 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -439,12 +439,20 @@ String String::printf(const char *fmt, ...) { int len = vsnprintf(output._str, _builtinCapacity, fmt, va); va_end(va); - if (len == -1) { - // MSVC doesn't return the size the full string would take up. - // Try increasing the size of the string until it fits. + if (len == -1 || len == _builtinCapacity - 1) { + // MSVC and IRIX don't return the size the full string would take up. + // MSVC returns -1, IRIX returns the number of characters actually written, + // which is at the most the size of the buffer minus one, as the string is + // truncated to fit. // We assume MSVC failed to output the correct, null-terminated string // if the return value is either -1 or size. + // For IRIX, because we lack a better mechanism, we assume failure + // if the return value equals size - 1. + // The downside to this is that whenever we try to format a string where the + // size is 1 below the built-in capacity, the size is needlessly increased. + + // Try increasing the size of the string until it fits. int size = _builtinCapacity; do { size *= 2; @@ -455,7 +463,7 @@ String String::printf(const char *fmt, ...) { va_start(va, fmt); len = vsnprintf(output._str, size, fmt, va); va_end(va); - } while (len == -1 || len >= size); + } while (len == -1 || len >= size - 1); output._size = len; } else if (len < (int)_builtinCapacity) { // vsnprintf succeeded -- cgit v1.2.3