1// Copyright 2002 The RE2 Authors. All Rights Reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5#include "util/util.h" 6 7namespace re2 { 8 9static void StringAppendV(string* dst, const char* format, va_list ap) { 10 // First try with a small fixed size buffer 11 char space[1024]; 12 13 // It's possible for methods that use a va_list to invalidate 14 // the data in it upon use. The fix is to make a copy 15 // of the structure before using it and use that copy instead. 16 va_list backup_ap; 17 va_copy(backup_ap, ap); 18 int result = vsnprintf(space, sizeof(space), format, backup_ap); 19 va_end(backup_ap); 20 21 if ((result >= 0) && (result < sizeof(space))) { 22 // It fit 23 dst->append(space, result); 24 return; 25 } 26 27 // Repeatedly increase buffer size until it fits 28 int length = sizeof(space); 29 while (true) { 30 if (result < 0) { 31 // Older behavior: just try doubling the buffer size 32 length *= 2; 33 } else { 34 // 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