diff options
-rw-r--r-- | src/core/SkString.cpp | 96 | ||||
-rw-r--r-- | tests/StringTest.cpp | 10 |
2 files changed, 64 insertions, 42 deletions
diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp index 554cde8f9f..707e8befb8 100644 --- a/src/core/SkString.cpp +++ b/src/core/SkString.cpp @@ -5,48 +5,60 @@ * found in the LICENSE file. */ +#include "SkString.h" +#include <stdarg.h> +#include <cstdio> #include "SkAtomics.h" #include "SkSafeMath.h" -#include "SkString.h" #include "SkUtils.h" -#include <stdarg.h> -#include <stdio.h> // number of bytes (on the stack) to receive the printf result static const size_t kBufferSize = 1024; -#define ARGS_TO_BUFFER(format, buffer, size, written) \ - do { \ - va_list args; \ - va_start(args, format); \ - written = vsnprintf(buffer, size, format, args); \ - SkASSERT(written >= 0 && written < SkToInt(size)); \ - va_end(args); \ +static const char* apply_format_string(const char* format, va_list args, char* stackBuffer, + size_t stackBufferSize, int* length, SkString* heapBuffer) { + va_list argsCopy; + va_copy(argsCopy, args); + *length = std::vsnprintf(stackBuffer, stackBufferSize, format, args); + if (*length < 0) { + SkDebugf("SkString: vsnprintf reported error."); + va_end(argsCopy); + *length = 0; + return stackBuffer; + } + if (*length < SkToInt(stackBufferSize)) { + va_end(argsCopy); + return stackBuffer; + } + heapBuffer->resize(*length); + SkDEBUGCODE(int check =) + std::vsnprintf(heapBuffer->writable_str(), *length + 1, format, argsCopy); + SkASSERT(check == *length); + va_end(argsCopy); + return heapBuffer->c_str(); +} + +#define ARGS_TO_BUFFER(format, buffer, size, written, result) \ + SkString overflow; \ + do { \ + va_list args; \ + va_start(args, format); \ + result = apply_format_string(format, args, buffer, size, &written, &overflow); \ + va_end(args); \ } while (0) -#define V_SKSTRING_PRINTF(output, format) \ - do { \ - va_list args; \ - va_start(args, format); \ - char buffer[kBufferSize]; \ - int length = vsnprintf(buffer, sizeof(buffer), format, args); \ - va_end(args); \ - if (length < 0) { \ - break; \ - } \ - if (length < (int)sizeof(buffer)) { \ - output.set(buffer, length); \ - break; \ - } \ - SkString tmp((size_t)length); \ - va_start(args, format); \ - SkDEBUGCODE(int check = ) vsnprintf(tmp.writable_str(), \ - length + 1, format, args); \ - va_end(args); \ - SkASSERT(check == length); \ - output = std::move(tmp); \ - SkASSERT(output[length] == '\0'); \ - } while (false) +#define V_SKSTRING_PRINTF(output, format) \ + do { \ + char buffer[kBufferSize]; \ + va_list args; \ + va_start(args, format); \ + int length; \ + auto result = apply_format_string(format, args, buffer, kBufferSize, &length, &output); \ + SkASSERT(result == output.c_str() || result == buffer); \ + if (result == buffer) { \ + output.set(buffer, length); \ + } \ + } while (0) /////////////////////////////////////////////////////////////////////////////// @@ -491,15 +503,16 @@ void SkString::printf(const char format[], ...) { } void SkString::appendf(const char format[], ...) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length; - ARGS_TO_BUFFER(format, buffer, kBufferSize, length); + const char* result; + ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result); - this->append(buffer, length); + this->append(result, length); } void SkString::appendVAList(const char format[], va_list args) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length = vsnprintf(buffer, kBufferSize, format, args); SkASSERT(length >= 0 && length < SkToInt(kBufferSize)); @@ -507,15 +520,16 @@ void SkString::appendVAList(const char format[], va_list args) { } void SkString::prependf(const char format[], ...) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length; - ARGS_TO_BUFFER(format, buffer, kBufferSize, length); + const char* result; + ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result); - this->prepend(buffer, length); + this->prepend(result, length); } void SkString::prependVAList(const char format[], va_list args) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length = vsnprintf(buffer, kBufferSize, format, args); SkASSERT(length >= 0 && length < SkToInt(kBufferSize)); diff --git a/tests/StringTest.cpp b/tests/StringTest.cpp index 06c18f6f53..f8c319e9be 100644 --- a/tests/StringTest.cpp +++ b/tests/StringTest.cpp @@ -192,7 +192,15 @@ DEF_TEST(String, reporter) { REPORTER_ASSERT(reporter, a.size() == 2000); for (size_t i = 0; i < a.size(); ++i) { if (a[i] != ' ') { - ERRORF(reporter, "SkStringPrintf fail: a[%d] = '%c'", i, a[i]); + ERRORF(reporter, "SkString::printf fail: a[%d] = '%c'", i, a[i]); + break; + } + } + a.appendf("%2000s", " "); + REPORTER_ASSERT(reporter, a.size() == 4000); + for (size_t i = 0; i < a.size(); ++i) { + if (a[i] != ' ') { + ERRORF(reporter, "SkString::appendf fail: a[%d] = '%c'", i, a[i]); break; } } |