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