|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #include "base/string_util.h" |
|
6 |
|
7 #include "build/build_config.h" |
|
8 |
|
9 #include <ctype.h> |
|
10 #include <errno.h> |
|
11 #include <math.h> |
|
12 #include <stdarg.h> |
|
13 #include <stdio.h> |
|
14 #include <stdlib.h> |
|
15 #include <string.h> |
|
16 #include <time.h> |
|
17 #include <wchar.h> |
|
18 #include <wctype.h> |
|
19 |
|
20 #include <algorithm> |
|
21 #include <vector> |
|
22 |
|
23 #include "base/basictypes.h" |
|
24 #include "base/logging.h" |
|
25 #include "base/singleton.h" |
|
26 |
|
27 namespace { |
|
28 |
|
29 // Force the singleton used by Empty[W]String[16] to be a unique type. This |
|
30 // prevents other code that might accidentally use Singleton<string> from |
|
31 // getting our internal one. |
|
32 struct EmptyStrings { |
|
33 EmptyStrings() {} |
|
34 const std::string s; |
|
35 const std::wstring ws; |
|
36 const string16 s16; |
|
37 }; |
|
38 |
|
39 // Hack to convert any char-like type to its unsigned counterpart. |
|
40 // For example, it will convert char, signed char and unsigned char to unsigned |
|
41 // char. |
|
42 template<typename T> |
|
43 struct ToUnsigned { |
|
44 typedef T Unsigned; |
|
45 }; |
|
46 |
|
47 template<> |
|
48 struct ToUnsigned<char> { |
|
49 typedef unsigned char Unsigned; |
|
50 }; |
|
51 template<> |
|
52 struct ToUnsigned<signed char> { |
|
53 typedef unsigned char Unsigned; |
|
54 }; |
|
55 template<> |
|
56 struct ToUnsigned<wchar_t> { |
|
57 #if defined(WCHAR_T_IS_UTF16) |
|
58 typedef unsigned short Unsigned; |
|
59 #elif defined(WCHAR_T_IS_UTF32) |
|
60 typedef uint32_t Unsigned; |
|
61 #endif |
|
62 }; |
|
63 template<> |
|
64 struct ToUnsigned<short> { |
|
65 typedef unsigned short Unsigned; |
|
66 }; |
|
67 |
|
68 // Generalized string-to-number conversion. |
|
69 // |
|
70 // StringToNumberTraits should provide: |
|
71 // - a typedef for string_type, the STL string type used as input. |
|
72 // - a typedef for value_type, the target numeric type. |
|
73 // - a static function, convert_func, which dispatches to an appropriate |
|
74 // strtol-like function and returns type value_type. |
|
75 // - a static function, valid_func, which validates |input| and returns a bool |
|
76 // indicating whether it is in proper form. This is used to check for |
|
77 // conditions that convert_func tolerates but should result in |
|
78 // StringToNumber returning false. For strtol-like funtions, valid_func |
|
79 // should check for leading whitespace. |
|
80 template<typename StringToNumberTraits> |
|
81 bool StringToNumber(const typename StringToNumberTraits::string_type& input, |
|
82 typename StringToNumberTraits::value_type* output) { |
|
83 typedef StringToNumberTraits traits; |
|
84 |
|
85 errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. |
|
86 typename traits::string_type::value_type* endptr = NULL; |
|
87 typename traits::value_type value = traits::convert_func(input.c_str(), |
|
88 &endptr); |
|
89 *output = value; |
|
90 |
|
91 // Cases to return false: |
|
92 // - If errno is ERANGE, there was an overflow or underflow. |
|
93 // - If the input string is empty, there was nothing to parse. |
|
94 // - If endptr does not point to the end of the string, there are either |
|
95 // characters remaining in the string after a parsed number, or the string |
|
96 // does not begin with a parseable number. endptr is compared to the |
|
97 // expected end given the string's stated length to correctly catch cases |
|
98 // where the string contains embedded NUL characters. |
|
99 // - valid_func determines that the input is not in preferred form. |
|
100 return errno == 0 && |
|
101 !input.empty() && |
|
102 input.c_str() + input.length() == endptr && |
|
103 traits::valid_func(input); |
|
104 } |
|
105 |
|
106 class StringToLongTraits { |
|
107 public: |
|
108 typedef std::string string_type; |
|
109 typedef long value_type; |
|
110 static const int kBase = 10; |
|
111 static inline value_type convert_func(const string_type::value_type* str, |
|
112 string_type::value_type** endptr) { |
|
113 return strtol(str, endptr, kBase); |
|
114 } |
|
115 static inline bool valid_func(const string_type& str) { |
|
116 return !str.empty() && !isspace(str[0]); |
|
117 } |
|
118 }; |
|
119 |
|
120 class String16ToLongTraits { |
|
121 public: |
|
122 typedef string16 string_type; |
|
123 typedef long value_type; |
|
124 static const int kBase = 10; |
|
125 static inline value_type convert_func(const string_type::value_type* str, |
|
126 string_type::value_type** endptr) { |
|
127 #if defined(WCHAR_T_IS_UTF16) |
|
128 return wcstol(str, endptr, kBase); |
|
129 #elif defined(WCHAR_T_IS_UTF32) |
|
130 std::string ascii_string = UTF16ToASCII(string16(str)); |
|
131 char* ascii_end = NULL; |
|
132 value_type ret = strtol(ascii_string.c_str(), &ascii_end, kBase); |
|
133 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
|
134 *endptr = |
|
135 const_cast<string_type::value_type*>(str) + ascii_string.length(); |
|
136 } |
|
137 return ret; |
|
138 #endif |
|
139 } |
|
140 static inline bool valid_func(const string_type& str) { |
|
141 return !str.empty() && !iswspace(str[0]); |
|
142 } |
|
143 }; |
|
144 |
|
145 class StringToInt64Traits { |
|
146 public: |
|
147 typedef std::string string_type; |
|
148 typedef int64_t value_type; |
|
149 static const int kBase = 10; |
|
150 static inline value_type convert_func(const string_type::value_type* str, |
|
151 string_type::value_type** endptr) { |
|
152 #ifdef OS_WIN |
|
153 return _strtoi64(str, endptr, kBase); |
|
154 #else // assume OS_POSIX |
|
155 return strtoll(str, endptr, kBase); |
|
156 #endif |
|
157 } |
|
158 static inline bool valid_func(const string_type& str) { |
|
159 return !str.empty() && !isspace(str[0]); |
|
160 } |
|
161 }; |
|
162 |
|
163 class String16ToInt64Traits { |
|
164 public: |
|
165 typedef string16 string_type; |
|
166 typedef int64_t value_type; |
|
167 static const int kBase = 10; |
|
168 static inline value_type convert_func(const string_type::value_type* str, |
|
169 string_type::value_type** endptr) { |
|
170 #ifdef OS_WIN |
|
171 return _wcstoi64(str, endptr, kBase); |
|
172 #else // assume OS_POSIX |
|
173 std::string ascii_string = UTF16ToASCII(string16(str)); |
|
174 char* ascii_end = NULL; |
|
175 value_type ret = strtoll(ascii_string.c_str(), &ascii_end, kBase); |
|
176 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
|
177 *endptr = |
|
178 const_cast<string_type::value_type*>(str) + ascii_string.length(); |
|
179 } |
|
180 return ret; |
|
181 #endif |
|
182 } |
|
183 static inline bool valid_func(const string_type& str) { |
|
184 return !str.empty() && !iswspace(str[0]); |
|
185 } |
|
186 }; |
|
187 |
|
188 } // namespace |
|
189 |
|
190 |
|
191 namespace base { |
|
192 |
|
193 bool IsWprintfFormatPortable(const wchar_t* format) { |
|
194 for (const wchar_t* position = format; *position != '\0'; ++position) { |
|
195 |
|
196 if (*position == '%') { |
|
197 bool in_specification = true; |
|
198 bool modifier_l = false; |
|
199 while (in_specification) { |
|
200 // Eat up characters until reaching a known specifier. |
|
201 if (*++position == '\0') { |
|
202 // The format string ended in the middle of a specification. Call |
|
203 // it portable because no unportable specifications were found. The |
|
204 // string is equally broken on all platforms. |
|
205 return true; |
|
206 } |
|
207 |
|
208 if (*position == 'l') { |
|
209 // 'l' is the only thing that can save the 's' and 'c' specifiers. |
|
210 modifier_l = true; |
|
211 } else if (((*position == 's' || *position == 'c') && !modifier_l) || |
|
212 *position == 'S' || *position == 'C' || *position == 'F' || |
|
213 *position == 'D' || *position == 'O' || *position == 'U') { |
|
214 // Not portable. |
|
215 return false; |
|
216 } |
|
217 |
|
218 if (wcschr(L"diouxXeEfgGaAcspn%", *position)) { |
|
219 // Portable, keep scanning the rest of the format string. |
|
220 in_specification = false; |
|
221 } |
|
222 } |
|
223 } |
|
224 |
|
225 } |
|
226 |
|
227 return true; |
|
228 } |
|
229 |
|
230 |
|
231 } // namespace base |
|
232 |
|
233 static const wchar_t kWhitespaceWide[] = { |
|
234 0x0009, // <control-0009> to <control-000D> |
|
235 0x000A, |
|
236 0x000B, |
|
237 0x000C, |
|
238 0x000D, |
|
239 0x0020, // Space |
|
240 0x0085, // <control-0085> |
|
241 0x00A0, // No-Break Space |
|
242 0x1680, // Ogham Space Mark |
|
243 0x180E, // Mongolian Vowel Separator |
|
244 0x2000, // En Quad to Hair Space |
|
245 0x2001, |
|
246 0x2002, |
|
247 0x2003, |
|
248 0x2004, |
|
249 0x2005, |
|
250 0x2006, |
|
251 0x2007, |
|
252 0x2008, |
|
253 0x2009, |
|
254 0x200A, |
|
255 0x200C, // Zero Width Non-Joiner |
|
256 0x2028, // Line Separator |
|
257 0x2029, // Paragraph Separator |
|
258 0x202F, // Narrow No-Break Space |
|
259 0x205F, // Medium Mathematical Space |
|
260 0x3000, // Ideographic Space |
|
261 0 |
|
262 }; |
|
263 static const char kWhitespaceASCII[] = { |
|
264 0x09, // <control-0009> to <control-000D> |
|
265 0x0A, |
|
266 0x0B, |
|
267 0x0C, |
|
268 0x0D, |
|
269 0x20, // Space |
|
270 0 |
|
271 }; |
|
272 |
|
273 template<typename STR> |
|
274 TrimPositions TrimStringT(const STR& input, |
|
275 const typename STR::value_type trim_chars[], |
|
276 TrimPositions positions, |
|
277 STR* output) { |
|
278 // Find the edges of leading/trailing whitespace as desired. |
|
279 const typename STR::size_type last_char = input.length() - 1; |
|
280 const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ? |
|
281 input.find_first_not_of(trim_chars) : 0; |
|
282 const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ? |
|
283 input.find_last_not_of(trim_chars) : last_char; |
|
284 |
|
285 // When the string was all whitespace, report that we stripped off whitespace |
|
286 // from whichever position the caller was interested in. For empty input, we |
|
287 // stripped no whitespace, but we still need to clear |output|. |
|
288 if (input.empty() || |
|
289 (first_good_char == STR::npos) || (last_good_char == STR::npos)) { |
|
290 bool input_was_empty = input.empty(); // in case output == &input |
|
291 output->clear(); |
|
292 return input_was_empty ? TRIM_NONE : positions; |
|
293 } |
|
294 |
|
295 // Trim the whitespace. |
|
296 *output = |
|
297 input.substr(first_good_char, last_good_char - first_good_char + 1); |
|
298 |
|
299 // Return where we trimmed from. |
|
300 return static_cast<TrimPositions>( |
|
301 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | |
|
302 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); |
|
303 } |
|
304 |
|
305 TrimPositions TrimWhitespace(const std::wstring& input, |
|
306 TrimPositions positions, |
|
307 std::wstring* output) { |
|
308 return TrimStringT(input, kWhitespaceWide, positions, output); |
|
309 } |
|
310 |
|
311 TrimPositions TrimWhitespaceASCII(const std::string& input, |
|
312 TrimPositions positions, |
|
313 std::string* output) { |
|
314 return TrimStringT(input, kWhitespaceASCII, positions, output); |
|
315 } |
|
316 |
|
317 // This function is only for backward-compatibility. |
|
318 // To be removed when all callers are updated. |
|
319 TrimPositions TrimWhitespace(const std::string& input, |
|
320 TrimPositions positions, |
|
321 std::string* output) { |
|
322 return TrimWhitespaceASCII(input, positions, output); |
|
323 } |
|
324 |
|
325 std::string WideToASCII(const std::wstring& wide) { |
|
326 DCHECK(IsStringASCII(wide)); |
|
327 return std::string(wide.begin(), wide.end()); |
|
328 } |
|
329 |
|
330 std::wstring ASCIIToWide(const std::string& ascii) { |
|
331 DCHECK(IsStringASCII(ascii)); |
|
332 return std::wstring(ascii.begin(), ascii.end()); |
|
333 } |
|
334 |
|
335 std::string UTF16ToASCII(const string16& utf16) { |
|
336 DCHECK(IsStringASCII(utf16)); |
|
337 return std::string(utf16.begin(), utf16.end()); |
|
338 } |
|
339 |
|
340 string16 ASCIIToUTF16(const std::string& ascii) { |
|
341 DCHECK(IsStringASCII(ascii)); |
|
342 return string16(ascii.begin(), ascii.end()); |
|
343 } |
|
344 |
|
345 template<class STR> |
|
346 static bool DoIsStringASCII(const STR& str) { |
|
347 for (size_t i = 0; i < str.length(); i++) { |
|
348 typename ToUnsigned<typename STR::value_type>::Unsigned c = str[i]; |
|
349 if (c > 0x7F) |
|
350 return false; |
|
351 } |
|
352 return true; |
|
353 } |
|
354 |
|
355 bool IsStringASCII(const std::wstring& str) { |
|
356 return DoIsStringASCII(str); |
|
357 } |
|
358 |
|
359 #if !defined(WCHAR_T_IS_UTF16) |
|
360 bool IsStringASCII(const string16& str) { |
|
361 return DoIsStringASCII(str); |
|
362 } |
|
363 #endif |
|
364 |
|
365 bool IsStringASCII(const std::string& str) { |
|
366 return DoIsStringASCII(str); |
|
367 } |
|
368 |
|
369 // Overloaded wrappers around vsnprintf and vswprintf. The buf_size parameter |
|
370 // is the size of the buffer. These return the number of characters in the |
|
371 // formatted string excluding the NUL terminator. If the buffer is not |
|
372 // large enough to accommodate the formatted string without truncation, they |
|
373 // return the number of characters that would be in the fully-formatted string |
|
374 // (vsnprintf, and vswprintf on Windows), or -1 (vswprintf on POSIX platforms). |
|
375 inline int vsnprintfT(char* buffer, |
|
376 size_t buf_size, |
|
377 const char* format, |
|
378 va_list argptr) { |
|
379 return base::vsnprintf(buffer, buf_size, format, argptr); |
|
380 } |
|
381 |
|
382 inline int vsnprintfT(wchar_t* buffer, |
|
383 size_t buf_size, |
|
384 const wchar_t* format, |
|
385 va_list argptr) { |
|
386 return base::vswprintf(buffer, buf_size, format, argptr); |
|
387 } |
|
388 |
|
389 // Templatized backend for StringPrintF/StringAppendF. This does not finalize |
|
390 // the va_list, the caller is expected to do that. |
|
391 template <class StringType> |
|
392 static void StringAppendVT(StringType* dst, |
|
393 const typename StringType::value_type* format, |
|
394 va_list ap) { |
|
395 // First try with a small fixed size buffer. |
|
396 // This buffer size should be kept in sync with StringUtilTest.GrowBoundary |
|
397 // and StringUtilTest.StringPrintfBounds. |
|
398 typename StringType::value_type stack_buf[1024]; |
|
399 |
|
400 va_list backup_ap; |
|
401 base_va_copy(backup_ap, ap); |
|
402 |
|
403 #if !defined(OS_WIN) |
|
404 errno = 0; |
|
405 #endif |
|
406 int result = vsnprintfT(stack_buf, arraysize(stack_buf), format, backup_ap); |
|
407 va_end(backup_ap); |
|
408 |
|
409 if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) { |
|
410 // It fit. |
|
411 dst->append(stack_buf, result); |
|
412 return; |
|
413 } |
|
414 |
|
415 // Repeatedly increase buffer size until it fits. |
|
416 int mem_length = arraysize(stack_buf); |
|
417 while (true) { |
|
418 if (result < 0) { |
|
419 #if !defined(OS_WIN) |
|
420 // On Windows, vsnprintfT always returns the number of characters in a |
|
421 // fully-formatted string, so if we reach this point, something else is |
|
422 // wrong and no amount of buffer-doubling is going to fix it. |
|
423 if (errno != 0 && errno != EOVERFLOW) |
|
424 #endif |
|
425 { |
|
426 // If an error other than overflow occurred, it's never going to work. |
|
427 DLOG(WARNING) << "Unable to printf the requested string due to error."; |
|
428 return; |
|
429 } |
|
430 // Try doubling the buffer size. |
|
431 mem_length *= 2; |
|
432 } else { |
|
433 // We need exactly "result + 1" characters. |
|
434 mem_length = result + 1; |
|
435 } |
|
436 |
|
437 if (mem_length > 32 * 1024 * 1024) { |
|
438 // That should be plenty, don't try anything larger. This protects |
|
439 // against huge allocations when using vsnprintfT implementations that |
|
440 // return -1 for reasons other than overflow without setting errno. |
|
441 DLOG(WARNING) << "Unable to printf the requested string due to size."; |
|
442 return; |
|
443 } |
|
444 |
|
445 std::vector<typename StringType::value_type> mem_buf(mem_length); |
|
446 |
|
447 // Restore the va_list before we use it again. |
|
448 base_va_copy(backup_ap, ap); |
|
449 |
|
450 result = vsnprintfT(&mem_buf[0], mem_length, format, ap); |
|
451 va_end(backup_ap); |
|
452 |
|
453 if ((result >= 0) && (result < mem_length)) { |
|
454 // It fit. |
|
455 dst->append(&mem_buf[0], result); |
|
456 return; |
|
457 } |
|
458 } |
|
459 } |
|
460 |
|
461 namespace { |
|
462 |
|
463 template <typename STR, typename INT, typename UINT, bool NEG> |
|
464 struct IntToStringT { |
|
465 |
|
466 // This is to avoid a compiler warning about unary minus on unsigned type. |
|
467 // For example, say you had the following code: |
|
468 // template <typename INT> |
|
469 // INT abs(INT value) { return value < 0 ? -value : value; } |
|
470 // Even though if INT is unsigned, it's impossible for value < 0, so the |
|
471 // unary minus will never be taken, the compiler will still generate a |
|
472 // warning. We do a little specialization dance... |
|
473 template <typename INT2, typename UINT2, bool NEG2> |
|
474 struct ToUnsignedT { }; |
|
475 |
|
476 template <typename INT2, typename UINT2> |
|
477 struct ToUnsignedT<INT2, UINT2, false> { |
|
478 static UINT2 ToUnsigned(INT2 value) { |
|
479 return static_cast<UINT2>(value); |
|
480 } |
|
481 }; |
|
482 |
|
483 template <typename INT2, typename UINT2> |
|
484 struct ToUnsignedT<INT2, UINT2, true> { |
|
485 static UINT2 ToUnsigned(INT2 value) { |
|
486 return static_cast<UINT2>(value < 0 ? -value : value); |
|
487 } |
|
488 }; |
|
489 |
|
490 // This set of templates is very similar to the above templates, but |
|
491 // for testing whether an integer is negative. |
|
492 template <typename INT2, bool NEG2> |
|
493 struct TestNegT {}; |
|
494 template <typename INT2> |
|
495 struct TestNegT<INT2, false> { |
|
496 static bool TestNeg(INT2 value) { |
|
497 // value is unsigned, and can never be negative. |
|
498 return false; |
|
499 } |
|
500 }; |
|
501 template <typename INT2> |
|
502 struct TestNegT<INT2, true> { |
|
503 static bool TestNeg(INT2 value) { |
|
504 return value < 0; |
|
505 } |
|
506 }; |
|
507 |
|
508 static STR IntToString(INT value) { |
|
509 // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. |
|
510 // So round up to allocate 3 output characters per byte, plus 1 for '-'. |
|
511 const int kOutputBufSize = 3 * sizeof(INT) + 1; |
|
512 |
|
513 // Allocate the whole string right away, we will right back to front, and |
|
514 // then return the substr of what we ended up using. |
|
515 STR outbuf(kOutputBufSize, 0); |
|
516 |
|
517 bool is_neg = TestNegT<INT, NEG>::TestNeg(value); |
|
518 // Even though is_neg will never be true when INT is parameterized as |
|
519 // unsigned, even the presence of the unary operation causes a warning. |
|
520 UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value); |
|
521 |
|
522 for (typename STR::iterator it = outbuf.end();;) { |
|
523 --it; |
|
524 DCHECK(it != outbuf.begin()); |
|
525 *it = static_cast<typename STR::value_type>((res % 10) + '0'); |
|
526 res /= 10; |
|
527 |
|
528 // We're done.. |
|
529 if (res == 0) { |
|
530 if (is_neg) { |
|
531 --it; |
|
532 DCHECK(it != outbuf.begin()); |
|
533 *it = static_cast<typename STR::value_type>('-'); |
|
534 } |
|
535 return STR(it, outbuf.end()); |
|
536 } |
|
537 } |
|
538 NOTREACHED(); |
|
539 return STR(); |
|
540 } |
|
541 }; |
|
542 |
|
543 } |
|
544 |
|
545 std::string IntToString(int value) { |
|
546 return IntToStringT<std::string, int, unsigned int, true>:: |
|
547 IntToString(value); |
|
548 } |
|
549 std::wstring IntToWString(int value) { |
|
550 return IntToStringT<std::wstring, int, unsigned int, true>:: |
|
551 IntToString(value); |
|
552 } |
|
553 std::string UintToString(unsigned int value) { |
|
554 return IntToStringT<std::string, unsigned int, unsigned int, false>:: |
|
555 IntToString(value); |
|
556 } |
|
557 std::wstring UintToWString(unsigned int value) { |
|
558 return IntToStringT<std::wstring, unsigned int, unsigned int, false>:: |
|
559 IntToString(value); |
|
560 } |
|
561 std::string Int64ToString(int64_t value) { |
|
562 return IntToStringT<std::string, int64_t, uint64_t, true>:: |
|
563 IntToString(value); |
|
564 } |
|
565 std::wstring Int64ToWString(int64_t value) { |
|
566 return IntToStringT<std::wstring, int64_t, uint64_t, true>:: |
|
567 IntToString(value); |
|
568 } |
|
569 std::string Uint64ToString(uint64_t value) { |
|
570 return IntToStringT<std::string, uint64_t, uint64_t, false>:: |
|
571 IntToString(value); |
|
572 } |
|
573 std::wstring Uint64ToWString(uint64_t value) { |
|
574 return IntToStringT<std::wstring, uint64_t, uint64_t, false>:: |
|
575 IntToString(value); |
|
576 } |
|
577 |
|
578 // Lower-level routine that takes a va_list and appends to a specified |
|
579 // string. All other routines are just convenience wrappers around it. |
|
580 static void StringAppendV(std::string* dst, const char* format, va_list ap) { |
|
581 StringAppendVT(dst, format, ap); |
|
582 } |
|
583 |
|
584 static void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) { |
|
585 StringAppendVT(dst, format, ap); |
|
586 } |
|
587 |
|
588 std::string StringPrintf(const char* format, ...) { |
|
589 va_list ap; |
|
590 va_start(ap, format); |
|
591 std::string result; |
|
592 StringAppendV(&result, format, ap); |
|
593 va_end(ap); |
|
594 return result; |
|
595 } |
|
596 |
|
597 std::wstring StringPrintf(const wchar_t* format, ...) { |
|
598 va_list ap; |
|
599 va_start(ap, format); |
|
600 std::wstring result; |
|
601 StringAppendV(&result, format, ap); |
|
602 va_end(ap); |
|
603 return result; |
|
604 } |
|
605 |
|
606 const std::string& SStringPrintf(std::string* dst, const char* format, ...) { |
|
607 va_list ap; |
|
608 va_start(ap, format); |
|
609 dst->clear(); |
|
610 StringAppendV(dst, format, ap); |
|
611 va_end(ap); |
|
612 return *dst; |
|
613 } |
|
614 |
|
615 const std::wstring& SStringPrintf(std::wstring* dst, |
|
616 const wchar_t* format, ...) { |
|
617 va_list ap; |
|
618 va_start(ap, format); |
|
619 dst->clear(); |
|
620 StringAppendV(dst, format, ap); |
|
621 va_end(ap); |
|
622 return *dst; |
|
623 } |
|
624 |
|
625 void StringAppendF(std::string* dst, const char* format, ...) { |
|
626 va_list ap; |
|
627 va_start(ap, format); |
|
628 StringAppendV(dst, format, ap); |
|
629 va_end(ap); |
|
630 } |
|
631 |
|
632 void StringAppendF(std::wstring* dst, const wchar_t* format, ...) { |
|
633 va_list ap; |
|
634 va_start(ap, format); |
|
635 StringAppendV(dst, format, ap); |
|
636 va_end(ap); |
|
637 } |
|
638 |
|
639 template<typename STR> |
|
640 static void SplitStringT(const STR& str, |
|
641 const typename STR::value_type s, |
|
642 bool trim_whitespace, |
|
643 std::vector<STR>* r) { |
|
644 size_t last = 0; |
|
645 size_t i; |
|
646 size_t c = str.size(); |
|
647 for (i = 0; i <= c; ++i) { |
|
648 if (i == c || str[i] == s) { |
|
649 size_t len = i - last; |
|
650 STR tmp = str.substr(last, len); |
|
651 if (trim_whitespace) { |
|
652 STR t_tmp; |
|
653 TrimWhitespace(tmp, TRIM_ALL, &t_tmp); |
|
654 r->push_back(t_tmp); |
|
655 } else { |
|
656 r->push_back(tmp); |
|
657 } |
|
658 last = i + 1; |
|
659 } |
|
660 } |
|
661 } |
|
662 |
|
663 void SplitString(const std::wstring& str, |
|
664 wchar_t s, |
|
665 std::vector<std::wstring>* r) { |
|
666 SplitStringT(str, s, true, r); |
|
667 } |
|
668 |
|
669 void SplitString(const std::string& str, |
|
670 char s, |
|
671 std::vector<std::string>* r) { |
|
672 SplitStringT(str, s, true, r); |
|
673 } |
|
674 |
|
675 // For the various *ToInt conversions, there are no *ToIntTraits classes to use |
|
676 // because there's no such thing as strtoi. Use *ToLongTraits through a cast |
|
677 // instead, requiring that long and int are compatible and equal-width. They |
|
678 // are on our target platforms. |
|
679 |
|
680 // XXX Sigh. |
|
681 |
|
682 #if !defined(ARCH_CPU_64_BITS) |
|
683 bool StringToInt(const std::string& input, int* output) { |
|
684 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); |
|
685 return StringToNumber<StringToLongTraits>(input, |
|
686 reinterpret_cast<long*>(output)); |
|
687 } |
|
688 |
|
689 bool StringToInt(const string16& input, int* output) { |
|
690 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); |
|
691 return StringToNumber<String16ToLongTraits>(input, |
|
692 reinterpret_cast<long*>(output)); |
|
693 } |
|
694 |
|
695 #else |
|
696 bool StringToInt(const std::string& input, int* output) { |
|
697 long tmp; |
|
698 bool ok = StringToNumber<StringToLongTraits>(input, &tmp); |
|
699 if (!ok || tmp > kint32max) { |
|
700 return false; |
|
701 } |
|
702 *output = static_cast<int>(tmp); |
|
703 return true; |
|
704 } |
|
705 |
|
706 bool StringToInt(const string16& input, int* output) { |
|
707 long tmp; |
|
708 bool ok = StringToNumber<String16ToLongTraits>(input, &tmp); |
|
709 if (!ok || tmp > kint32max) { |
|
710 return false; |
|
711 } |
|
712 *output = static_cast<int>(tmp); |
|
713 return true; |
|
714 } |
|
715 #endif // !defined(ARCH_CPU_64_BITS) |
|
716 |
|
717 bool StringToInt64(const std::string& input, int64_t* output) { |
|
718 return StringToNumber<StringToInt64Traits>(input, output); |
|
719 } |
|
720 |
|
721 bool StringToInt64(const string16& input, int64_t* output) { |
|
722 return StringToNumber<String16ToInt64Traits>(input, output); |
|
723 } |
|
724 |
|
725 int StringToInt(const std::string& value) { |
|
726 int result; |
|
727 StringToInt(value, &result); |
|
728 return result; |
|
729 } |
|
730 |
|
731 int StringToInt(const string16& value) { |
|
732 int result; |
|
733 StringToInt(value, &result); |
|
734 return result; |
|
735 } |
|
736 |
|
737 int64_t StringToInt64(const std::string& value) { |
|
738 int64_t result; |
|
739 StringToInt64(value, &result); |
|
740 return result; |
|
741 } |
|
742 |
|
743 int64_t StringToInt64(const string16& value) { |
|
744 int64_t result; |
|
745 StringToInt64(value, &result); |
|
746 return result; |
|
747 } |
|
748 |
|
749 // The following code is compatible with the OpenBSD lcpy interface. See: |
|
750 // http://www.gratisoft.us/todd/papers/strlcpy.html |
|
751 // ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c |
|
752 |
|
753 namespace { |
|
754 |
|
755 template <typename CHAR> |
|
756 size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { |
|
757 for (size_t i = 0; i < dst_size; ++i) { |
|
758 if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. |
|
759 return i; |
|
760 } |
|
761 |
|
762 // We were left off at dst_size. We over copied 1 byte. Null terminate. |
|
763 if (dst_size != 0) |
|
764 dst[dst_size - 1] = 0; |
|
765 |
|
766 // Count the rest of the |src|, and return it's length in characters. |
|
767 while (src[dst_size]) ++dst_size; |
|
768 return dst_size; |
|
769 } |
|
770 |
|
771 } // namespace |
|
772 |
|
773 size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { |
|
774 return lcpyT<char>(dst, src, dst_size); |
|
775 } |
|
776 size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { |
|
777 return lcpyT<wchar_t>(dst, src, dst_size); |
|
778 } |