OLD | NEW |
(Empty) | |
| 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 |
| 7 #ifndef va_copy |
| 8 #define va_copy(d,s) ((d) = (s)) //KLUGE: for MS compilers |
| 9 #endif |
| 10 |
| 11 namespace re2 { |
| 12 |
| 13 static void StringAppendV(string* dst, const char* format, va_list ap) { |
| 14 // First try with a small fixed size buffer |
| 15 char space[1024]; |
| 16 |
| 17 // It's possible for methods that use a va_list to invalidate |
| 18 // the data in it upon use. The fix is to make a copy |
| 19 // of the structure before using it and use that copy instead. |
| 20 va_list backup_ap; |
| 21 va_copy(backup_ap, ap); |
| 22 int result = vsnprintf(space, sizeof(space), format, backup_ap); |
| 23 va_end(backup_ap); |
| 24 |
| 25 if ((result >= 0) && (result < sizeof(space))) { |
| 26 // It fit |
| 27 dst->append(space, result); |
| 28 return; |
| 29 } |
| 30 |
| 31 // Repeatedly increase buffer size until it fits |
| 32 int length = sizeof(space); |
| 33 while (true) { |
| 34 if (result < 0) { |
| 35 // Older behavior: just try doubling the buffer size |
| 36 length *= 2; |
| 37 } else { |
| 38 // We need exactly "result+1" characters |
| 39 length = result+1; |
| 40 } |
| 41 char* buf = new char[length]; |
| 42 |
| 43 // Restore the va_list before we use it again |
| 44 va_copy(backup_ap, ap); |
| 45 result = vsnprintf(buf, length, format, backup_ap); |
| 46 va_end(backup_ap); |
| 47 |
| 48 if ((result >= 0) && (result < length)) { |
| 49 // It fit |
| 50 dst->append(buf, result); |
| 51 delete[] buf; |
| 52 return; |
| 53 } |
| 54 delete[] buf; |
| 55 } |
| 56 } |
| 57 |
| 58 string StringPrintf(const char* format, ...) { |
| 59 va_list ap; |
| 60 va_start(ap, format); |
| 61 string result; |
| 62 StringAppendV(&result, format, ap); |
| 63 va_end(ap); |
| 64 return result; |
| 65 } |
| 66 |
| 67 void SStringPrintf(string* dst, const char* format, ...) { |
| 68 va_list ap; |
| 69 va_start(ap, format); |
| 70 dst->clear(); |
| 71 StringAppendV(dst, format, ap); |
| 72 va_end(ap); |
| 73 } |
| 74 |
| 75 void StringAppendF(string* dst, const char* format, ...) { |
| 76 va_list ap; |
| 77 va_start(ap, format); |
| 78 StringAppendV(dst, format, ap); |
| 79 va_end(ap); |
| 80 } |
| 81 |
| 82 } // namespace re2 |
OLD | NEW |