stringprintf.cc revision 2ee91b4af4353b9e6a9d591c32fedfc58fd4ef35
146a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com// Copyright 2002 The RE2 Authors. All Rights Reserved. 246a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com// Use of this source code is governed by a BSD-style 346a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com// license that can be found in the LICENSE file. 446a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com 546a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com#include "util/util.h" 646a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com 746a8600405e678718271f62c5994119b8d3241e9robertphillips@google.comnamespace re2 { 80797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com 946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.comstatic void StringAppendV(string* dst, const char* format, va_list ap) { 1046a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com // First try with a small fixed size buffer 115c265d6fd3537c99304b153fc49066db3be46d46bsalomon@google.com char space[1024]; 125c265d6fd3537c99304b153fc49066db3be46d46bsalomon@google.com 135c265d6fd3537c99304b153fc49066db3be46d46bsalomon@google.com // It's possible for methods that use a va_list to invalidate 143ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com // the data in it upon use. The fix is to make a copy 153ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com // of the structure before using it and use that copy instead. 163ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com va_list backup_ap; 173ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com va_copy(backup_ap, ap); 185c265d6fd3537c99304b153fc49066db3be46d46bsalomon@google.com int result = vsnprintf(space, sizeof(space), format, backup_ap); 193ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com va_end(backup_ap); 203ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com 213ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com if ((result >= 0) && (result < sizeof(space))) { 223ac5eb571bda3422a2868ddcf67ac731e7242a92reed@google.com // It fit 235c265d6fd3537c99304b153fc49066db3be46d46bsalomon@google.com dst->append(space, result); 240797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com return; 250797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com } 260797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com 2746a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com // Repeatedly increase buffer size until it fits 2846a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com int length = sizeof(space); 290797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com while (true) { 3088cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org if (result < 0) { 3146a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com // Older behavior: just try doubling the buffer size 3246a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com length *= 2; 330797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com } else { 3446a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com // We need exactly "result+1" characters 35 length = result+1; 36 } 37 char* buf = new char[length]; 38 39 // Restore the va_list before we use it again 40 va_copy(backup_ap, ap); 41 result = vsnprintf(buf, length, format, backup_ap); 42 va_end(backup_ap); 43 44 if ((result >= 0) && (result < length)) { 45 // It fit 46 dst->append(buf, result); 47 delete[] buf; 48 return; 49 } 50 delete[] buf; 51 } 52} 53 54string StringPrintf(const char* format, ...) { 55 va_list ap; 56 va_start(ap, format); 57 string result; 58 StringAppendV(&result, format, ap); 59 va_end(ap); 60 return result; 61} 62 63void SStringPrintf(string* dst, const char* format, ...) { 64 va_list ap; 65 va_start(ap, format); 66 dst->clear(); 67 StringAppendV(dst, format, ap); 68 va_end(ap); 69} 70 71void StringAppendF(string* dst, const char* format, ...) { 72 va_list ap; 73 va_start(ap, format); 74 StringAppendV(dst, format, ap); 75 va_end(ap); 76} 77 78} // namespace re2 79