blob: 8643c57d139e04ae1866892110b43b0368797e83 [file] [log] [blame]
Elliott Hugheseb4f6142011-07-15 17:43:51 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Elliott Hugheseb4f6142011-07-15 17:43:51 -07002
3#include "stringprintf.h"
4
5#include <stdio.h>
6
7void StringAppendV(std::string* dst, const char* format, va_list ap) {
8 // First try with a small fixed size buffer
9 char space[1024];
10
11 // It's possible for methods that use a va_list to invalidate
12 // the data in it upon use. The fix is to make a copy
13 // of the structure before using it and use that copy instead.
14 va_list backup_ap;
15 va_copy(backup_ap, ap);
16 int result = vsnprintf(space, sizeof(space), format, backup_ap);
17 va_end(backup_ap);
18
19 if (result < int(sizeof(space))) {
20 if (result >= 0) {
21 // Normal case -- everything fit.
22 dst->append(space, result);
23 return;
24 }
25
26 if (result < 0) {
27 // Just an error.
28 return;
29 }
30 }
31
32 // Increase the buffer size to the size requested by vsnprintf,
33 // plus one for the closing \0.
34 int length = result+1;
35 char* buf = new char[length];
36
37 // Restore the va_list before we use it again
38 va_copy(backup_ap, ap);
39 result = vsnprintf(buf, length, format, backup_ap);
40 va_end(backup_ap);
41
42 if (result >= 0 && result < length) {
43 // It fit
44 dst->append(buf, result);
45 }
46 delete[] buf;
47}
48
49std::string StringPrintf(const char* fmt, ...) {
50 va_list ap;
51 va_start(ap, fmt);
52 std::string result;
53 StringAppendV(&result, fmt, ap);
54 va_end(ap);
55 return result;
56}
57
58void StringAppendF(std::string* dst, const char* format, ...) {
59 va_list ap;
60 va_start(ap, format);
61 StringAppendV(dst, format, ap);
62 va_end(ap);
63}