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 namespace re2 {
8 
StringAppendV(string * dst,const char * format,va_list ap)9 static 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 
StringPrintf(const char * format,...)54 string 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 
SStringPrintf(string * dst,const char * format,...)63 void 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 
StringAppendF(string * dst,const char * format,...)71 void 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