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