OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/strings/stringprintf.h" | 5 #include "base/strings/stringprintf.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 11 matching lines...) Expand all Loading... |
22 // large enough to accommodate the formatted string without truncation, they | 22 // large enough to accommodate the formatted string without truncation, they |
23 // return the number of characters that would be in the fully-formatted string | 23 // return the number of characters that would be in the fully-formatted string |
24 // (vsnprintf, and vswprintf on Windows), or -1 (vswprintf on POSIX platforms). | 24 // (vsnprintf, and vswprintf on Windows), or -1 (vswprintf on POSIX platforms). |
25 inline int vsnprintfT(char* buffer, | 25 inline int vsnprintfT(char* buffer, |
26 size_t buf_size, | 26 size_t buf_size, |
27 const char* format, | 27 const char* format, |
28 va_list argptr) { | 28 va_list argptr) { |
29 return base::vsnprintf(buffer, buf_size, format, argptr); | 29 return base::vsnprintf(buffer, buf_size, format, argptr); |
30 } | 30 } |
31 | 31 |
32 #if defined(OS_WIN) | |
33 inline int vsnprintfT(wchar_t* buffer, | |
34 size_t buf_size, | |
35 const wchar_t* format, | |
36 va_list argptr) { | |
37 return base::vswprintf(buffer, buf_size, format, argptr); | |
38 } | |
39 #endif | |
40 | |
41 // Templatized backend for StringPrintF/StringAppendF. This does not finalize | 32 // Templatized backend for StringPrintF/StringAppendF. This does not finalize |
42 // the va_list, the caller is expected to do that. | 33 // the va_list, the caller is expected to do that. |
43 template <class StringType> | 34 template <class StringType> |
44 static void StringAppendVT(StringType* dst, | 35 static void StringAppendVT(StringType* dst, |
45 const typename StringType::value_type* format, | 36 const typename StringType::value_type* format, |
46 va_list ap) { | 37 va_list ap) { |
47 // First try with a small fixed size buffer. | 38 // First try with a small fixed size buffer. |
48 // This buffer size should be kept in sync with StringUtilTest.GrowBoundary | 39 // This buffer size should be kept in sync with StringUtilTest.GrowBoundary |
49 // and StringUtilTest.StringPrintfBounds. | 40 // and StringUtilTest.StringPrintfBounds. |
50 typename StringType::value_type stack_buf[1024]; | 41 typename StringType::value_type stack_buf[1024]; |
51 | 42 |
52 va_list ap_copy; | 43 va_list ap_copy; |
53 va_copy(ap_copy, ap); | 44 va_copy(ap_copy, ap); |
54 | 45 |
55 #if !defined(OS_WIN) | |
56 ScopedClearErrno clear_errno; | 46 ScopedClearErrno clear_errno; |
57 #endif | |
58 int result = vsnprintfT(stack_buf, arraysize(stack_buf), format, ap_copy); | 47 int result = vsnprintfT(stack_buf, arraysize(stack_buf), format, ap_copy); |
59 va_end(ap_copy); | 48 va_end(ap_copy); |
60 | 49 |
61 if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) { | 50 if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) { |
62 // It fit. | 51 // It fit. |
63 dst->append(stack_buf, result); | 52 dst->append(stack_buf, result); |
64 return; | 53 return; |
65 } | 54 } |
66 | 55 |
67 // Repeatedly increase buffer size until it fits. | 56 // Repeatedly increase buffer size until it fits. |
68 int mem_length = arraysize(stack_buf); | 57 int mem_length = arraysize(stack_buf); |
69 while (true) { | 58 while (true) { |
70 if (result < 0) { | 59 if (result < 0) { |
71 #if defined(OS_WIN) | |
72 // On Windows, vsnprintfT always returns the number of characters in a | |
73 // fully-formatted string, so if we reach this point, something else is | |
74 // wrong and no amount of buffer-doubling is going to fix it. | |
75 return; | |
76 #else | |
77 if (errno != 0 && errno != EOVERFLOW) | 60 if (errno != 0 && errno != EOVERFLOW) |
78 return; | 61 return; |
79 // Try doubling the buffer size. | 62 // Try doubling the buffer size. |
80 mem_length *= 2; | 63 mem_length *= 2; |
81 #endif | |
82 } else { | 64 } else { |
83 // We need exactly "result + 1" characters. | 65 // We need exactly "result + 1" characters. |
84 mem_length = result + 1; | 66 mem_length = result + 1; |
85 } | 67 } |
86 | 68 |
87 if (mem_length > 32 * 1024 * 1024) { | 69 if (mem_length > 32 * 1024 * 1024) { |
88 // That should be plenty, don't try anything larger. This protects | 70 // That should be plenty, don't try anything larger. This protects |
89 // against huge allocations when using vsnprintfT implementations that | 71 // against huge allocations when using vsnprintfT implementations that |
90 // return -1 for reasons other than overflow without setting errno. | 72 // return -1 for reasons other than overflow without setting errno. |
91 DLOG(WARNING) << "Unable to printf the requested string due to size."; | 73 DLOG(WARNING) << "Unable to printf the requested string due to size."; |
(...skipping 20 matching lines...) Expand all Loading... |
112 | 94 |
113 std::string StringPrintf(const char* format, ...) { | 95 std::string StringPrintf(const char* format, ...) { |
114 va_list ap; | 96 va_list ap; |
115 va_start(ap, format); | 97 va_start(ap, format); |
116 std::string result; | 98 std::string result; |
117 StringAppendV(&result, format, ap); | 99 StringAppendV(&result, format, ap); |
118 va_end(ap); | 100 va_end(ap); |
119 return result; | 101 return result; |
120 } | 102 } |
121 | 103 |
122 #if defined(OS_WIN) | |
123 std::wstring StringPrintf(const wchar_t* format, ...) { | |
124 va_list ap; | |
125 va_start(ap, format); | |
126 std::wstring result; | |
127 StringAppendV(&result, format, ap); | |
128 va_end(ap); | |
129 return result; | |
130 } | |
131 #endif | |
132 | |
133 std::string StringPrintV(const char* format, va_list ap) { | 104 std::string StringPrintV(const char* format, va_list ap) { |
134 std::string result; | 105 std::string result; |
135 StringAppendV(&result, format, ap); | 106 StringAppendV(&result, format, ap); |
136 return result; | 107 return result; |
137 } | 108 } |
138 | 109 |
139 const std::string& SStringPrintf(std::string* dst, const char* format, ...) { | 110 const std::string& SStringPrintf(std::string* dst, const char* format, ...) { |
140 va_list ap; | 111 va_list ap; |
141 va_start(ap, format); | 112 va_start(ap, format); |
142 dst->clear(); | 113 dst->clear(); |
143 StringAppendV(dst, format, ap); | 114 StringAppendV(dst, format, ap); |
144 va_end(ap); | 115 va_end(ap); |
145 return *dst; | 116 return *dst; |
146 } | 117 } |
147 | 118 |
148 #if defined(OS_WIN) | |
149 const std::wstring& SStringPrintf(std::wstring* dst, | |
150 const wchar_t* format, ...) { | |
151 va_list ap; | |
152 va_start(ap, format); | |
153 dst->clear(); | |
154 StringAppendV(dst, format, ap); | |
155 va_end(ap); | |
156 return *dst; | |
157 } | |
158 #endif | |
159 | |
160 void StringAppendF(std::string* dst, const char* format, ...) { | 119 void StringAppendF(std::string* dst, const char* format, ...) { |
161 va_list ap; | 120 va_list ap; |
162 va_start(ap, format); | 121 va_start(ap, format); |
163 StringAppendV(dst, format, ap); | 122 StringAppendV(dst, format, ap); |
164 va_end(ap); | 123 va_end(ap); |
165 } | 124 } |
166 | 125 |
167 #if defined(OS_WIN) | |
168 void StringAppendF(std::wstring* dst, const wchar_t* format, ...) { | |
169 va_list ap; | |
170 va_start(ap, format); | |
171 StringAppendV(dst, format, ap); | |
172 va_end(ap); | |
173 } | |
174 #endif | |
175 | |
176 void StringAppendV(std::string* dst, const char* format, va_list ap) { | 126 void StringAppendV(std::string* dst, const char* format, va_list ap) { |
177 StringAppendVT(dst, format, ap); | 127 StringAppendVT(dst, format, ap); |
178 } | 128 } |
179 | 129 |
180 #if defined(OS_WIN) | |
181 void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) { | |
182 StringAppendVT(dst, format, ap); | |
183 } | |
184 #endif | |
185 | |
186 } // namespace base | 130 } // namespace base |
OLD | NEW |