1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/string_util.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,778 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/string_util.h" 1.9 + 1.10 +#include "build/build_config.h" 1.11 + 1.12 +#include <ctype.h> 1.13 +#include <errno.h> 1.14 +#include <math.h> 1.15 +#include <stdarg.h> 1.16 +#include <stdio.h> 1.17 +#include <stdlib.h> 1.18 +#include <string.h> 1.19 +#include <time.h> 1.20 +#include <wchar.h> 1.21 +#include <wctype.h> 1.22 + 1.23 +#include <algorithm> 1.24 +#include <vector> 1.25 + 1.26 +#include "base/basictypes.h" 1.27 +#include "base/logging.h" 1.28 +#include "base/singleton.h" 1.29 + 1.30 +namespace { 1.31 + 1.32 +// Force the singleton used by Empty[W]String[16] to be a unique type. This 1.33 +// prevents other code that might accidentally use Singleton<string> from 1.34 +// getting our internal one. 1.35 +struct EmptyStrings { 1.36 + EmptyStrings() {} 1.37 + const std::string s; 1.38 + const std::wstring ws; 1.39 + const string16 s16; 1.40 +}; 1.41 + 1.42 +// Hack to convert any char-like type to its unsigned counterpart. 1.43 +// For example, it will convert char, signed char and unsigned char to unsigned 1.44 +// char. 1.45 +template<typename T> 1.46 +struct ToUnsigned { 1.47 + typedef T Unsigned; 1.48 +}; 1.49 + 1.50 +template<> 1.51 +struct ToUnsigned<char> { 1.52 + typedef unsigned char Unsigned; 1.53 +}; 1.54 +template<> 1.55 +struct ToUnsigned<signed char> { 1.56 + typedef unsigned char Unsigned; 1.57 +}; 1.58 +template<> 1.59 +struct ToUnsigned<wchar_t> { 1.60 +#if defined(WCHAR_T_IS_UTF16) 1.61 + typedef unsigned short Unsigned; 1.62 +#elif defined(WCHAR_T_IS_UTF32) 1.63 + typedef uint32_t Unsigned; 1.64 +#endif 1.65 +}; 1.66 +template<> 1.67 +struct ToUnsigned<short> { 1.68 + typedef unsigned short Unsigned; 1.69 +}; 1.70 + 1.71 +// Generalized string-to-number conversion. 1.72 +// 1.73 +// StringToNumberTraits should provide: 1.74 +// - a typedef for string_type, the STL string type used as input. 1.75 +// - a typedef for value_type, the target numeric type. 1.76 +// - a static function, convert_func, which dispatches to an appropriate 1.77 +// strtol-like function and returns type value_type. 1.78 +// - a static function, valid_func, which validates |input| and returns a bool 1.79 +// indicating whether it is in proper form. This is used to check for 1.80 +// conditions that convert_func tolerates but should result in 1.81 +// StringToNumber returning false. For strtol-like funtions, valid_func 1.82 +// should check for leading whitespace. 1.83 +template<typename StringToNumberTraits> 1.84 +bool StringToNumber(const typename StringToNumberTraits::string_type& input, 1.85 + typename StringToNumberTraits::value_type* output) { 1.86 + typedef StringToNumberTraits traits; 1.87 + 1.88 + errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. 1.89 + typename traits::string_type::value_type* endptr = NULL; 1.90 + typename traits::value_type value = traits::convert_func(input.c_str(), 1.91 + &endptr); 1.92 + *output = value; 1.93 + 1.94 + // Cases to return false: 1.95 + // - If errno is ERANGE, there was an overflow or underflow. 1.96 + // - If the input string is empty, there was nothing to parse. 1.97 + // - If endptr does not point to the end of the string, there are either 1.98 + // characters remaining in the string after a parsed number, or the string 1.99 + // does not begin with a parseable number. endptr is compared to the 1.100 + // expected end given the string's stated length to correctly catch cases 1.101 + // where the string contains embedded NUL characters. 1.102 + // - valid_func determines that the input is not in preferred form. 1.103 + return errno == 0 && 1.104 + !input.empty() && 1.105 + input.c_str() + input.length() == endptr && 1.106 + traits::valid_func(input); 1.107 +} 1.108 + 1.109 +class StringToLongTraits { 1.110 + public: 1.111 + typedef std::string string_type; 1.112 + typedef long value_type; 1.113 + static const int kBase = 10; 1.114 + static inline value_type convert_func(const string_type::value_type* str, 1.115 + string_type::value_type** endptr) { 1.116 + return strtol(str, endptr, kBase); 1.117 + } 1.118 + static inline bool valid_func(const string_type& str) { 1.119 + return !str.empty() && !isspace(str[0]); 1.120 + } 1.121 +}; 1.122 + 1.123 +class String16ToLongTraits { 1.124 + public: 1.125 + typedef string16 string_type; 1.126 + typedef long value_type; 1.127 + static const int kBase = 10; 1.128 + static inline value_type convert_func(const string_type::value_type* str, 1.129 + string_type::value_type** endptr) { 1.130 +#if defined(WCHAR_T_IS_UTF16) 1.131 + return wcstol(str, endptr, kBase); 1.132 +#elif defined(WCHAR_T_IS_UTF32) 1.133 + std::string ascii_string = UTF16ToASCII(string16(str)); 1.134 + char* ascii_end = NULL; 1.135 + value_type ret = strtol(ascii_string.c_str(), &ascii_end, kBase); 1.136 + if (ascii_string.c_str() + ascii_string.length() == ascii_end) { 1.137 + *endptr = 1.138 + const_cast<string_type::value_type*>(str) + ascii_string.length(); 1.139 + } 1.140 + return ret; 1.141 +#endif 1.142 + } 1.143 + static inline bool valid_func(const string_type& str) { 1.144 + return !str.empty() && !iswspace(str[0]); 1.145 + } 1.146 +}; 1.147 + 1.148 +class StringToInt64Traits { 1.149 + public: 1.150 + typedef std::string string_type; 1.151 + typedef int64_t value_type; 1.152 + static const int kBase = 10; 1.153 + static inline value_type convert_func(const string_type::value_type* str, 1.154 + string_type::value_type** endptr) { 1.155 +#ifdef OS_WIN 1.156 + return _strtoi64(str, endptr, kBase); 1.157 +#else // assume OS_POSIX 1.158 + return strtoll(str, endptr, kBase); 1.159 +#endif 1.160 + } 1.161 + static inline bool valid_func(const string_type& str) { 1.162 + return !str.empty() && !isspace(str[0]); 1.163 + } 1.164 +}; 1.165 + 1.166 +class String16ToInt64Traits { 1.167 + public: 1.168 + typedef string16 string_type; 1.169 + typedef int64_t value_type; 1.170 + static const int kBase = 10; 1.171 + static inline value_type convert_func(const string_type::value_type* str, 1.172 + string_type::value_type** endptr) { 1.173 +#ifdef OS_WIN 1.174 + return _wcstoi64(str, endptr, kBase); 1.175 +#else // assume OS_POSIX 1.176 + std::string ascii_string = UTF16ToASCII(string16(str)); 1.177 + char* ascii_end = NULL; 1.178 + value_type ret = strtoll(ascii_string.c_str(), &ascii_end, kBase); 1.179 + if (ascii_string.c_str() + ascii_string.length() == ascii_end) { 1.180 + *endptr = 1.181 + const_cast<string_type::value_type*>(str) + ascii_string.length(); 1.182 + } 1.183 + return ret; 1.184 +#endif 1.185 + } 1.186 + static inline bool valid_func(const string_type& str) { 1.187 + return !str.empty() && !iswspace(str[0]); 1.188 + } 1.189 +}; 1.190 + 1.191 +} // namespace 1.192 + 1.193 + 1.194 +namespace base { 1.195 + 1.196 +bool IsWprintfFormatPortable(const wchar_t* format) { 1.197 + for (const wchar_t* position = format; *position != '\0'; ++position) { 1.198 + 1.199 + if (*position == '%') { 1.200 + bool in_specification = true; 1.201 + bool modifier_l = false; 1.202 + while (in_specification) { 1.203 + // Eat up characters until reaching a known specifier. 1.204 + if (*++position == '\0') { 1.205 + // The format string ended in the middle of a specification. Call 1.206 + // it portable because no unportable specifications were found. The 1.207 + // string is equally broken on all platforms. 1.208 + return true; 1.209 + } 1.210 + 1.211 + if (*position == 'l') { 1.212 + // 'l' is the only thing that can save the 's' and 'c' specifiers. 1.213 + modifier_l = true; 1.214 + } else if (((*position == 's' || *position == 'c') && !modifier_l) || 1.215 + *position == 'S' || *position == 'C' || *position == 'F' || 1.216 + *position == 'D' || *position == 'O' || *position == 'U') { 1.217 + // Not portable. 1.218 + return false; 1.219 + } 1.220 + 1.221 + if (wcschr(L"diouxXeEfgGaAcspn%", *position)) { 1.222 + // Portable, keep scanning the rest of the format string. 1.223 + in_specification = false; 1.224 + } 1.225 + } 1.226 + } 1.227 + 1.228 + } 1.229 + 1.230 + return true; 1.231 +} 1.232 + 1.233 + 1.234 +} // namespace base 1.235 + 1.236 +static const wchar_t kWhitespaceWide[] = { 1.237 + 0x0009, // <control-0009> to <control-000D> 1.238 + 0x000A, 1.239 + 0x000B, 1.240 + 0x000C, 1.241 + 0x000D, 1.242 + 0x0020, // Space 1.243 + 0x0085, // <control-0085> 1.244 + 0x00A0, // No-Break Space 1.245 + 0x1680, // Ogham Space Mark 1.246 + 0x180E, // Mongolian Vowel Separator 1.247 + 0x2000, // En Quad to Hair Space 1.248 + 0x2001, 1.249 + 0x2002, 1.250 + 0x2003, 1.251 + 0x2004, 1.252 + 0x2005, 1.253 + 0x2006, 1.254 + 0x2007, 1.255 + 0x2008, 1.256 + 0x2009, 1.257 + 0x200A, 1.258 + 0x200C, // Zero Width Non-Joiner 1.259 + 0x2028, // Line Separator 1.260 + 0x2029, // Paragraph Separator 1.261 + 0x202F, // Narrow No-Break Space 1.262 + 0x205F, // Medium Mathematical Space 1.263 + 0x3000, // Ideographic Space 1.264 + 0 1.265 +}; 1.266 +static const char kWhitespaceASCII[] = { 1.267 + 0x09, // <control-0009> to <control-000D> 1.268 + 0x0A, 1.269 + 0x0B, 1.270 + 0x0C, 1.271 + 0x0D, 1.272 + 0x20, // Space 1.273 + 0 1.274 +}; 1.275 + 1.276 +template<typename STR> 1.277 +TrimPositions TrimStringT(const STR& input, 1.278 + const typename STR::value_type trim_chars[], 1.279 + TrimPositions positions, 1.280 + STR* output) { 1.281 + // Find the edges of leading/trailing whitespace as desired. 1.282 + const typename STR::size_type last_char = input.length() - 1; 1.283 + const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ? 1.284 + input.find_first_not_of(trim_chars) : 0; 1.285 + const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ? 1.286 + input.find_last_not_of(trim_chars) : last_char; 1.287 + 1.288 + // When the string was all whitespace, report that we stripped off whitespace 1.289 + // from whichever position the caller was interested in. For empty input, we 1.290 + // stripped no whitespace, but we still need to clear |output|. 1.291 + if (input.empty() || 1.292 + (first_good_char == STR::npos) || (last_good_char == STR::npos)) { 1.293 + bool input_was_empty = input.empty(); // in case output == &input 1.294 + output->clear(); 1.295 + return input_was_empty ? TRIM_NONE : positions; 1.296 + } 1.297 + 1.298 + // Trim the whitespace. 1.299 + *output = 1.300 + input.substr(first_good_char, last_good_char - first_good_char + 1); 1.301 + 1.302 + // Return where we trimmed from. 1.303 + return static_cast<TrimPositions>( 1.304 + ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | 1.305 + ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); 1.306 +} 1.307 + 1.308 +TrimPositions TrimWhitespace(const std::wstring& input, 1.309 + TrimPositions positions, 1.310 + std::wstring* output) { 1.311 + return TrimStringT(input, kWhitespaceWide, positions, output); 1.312 +} 1.313 + 1.314 +TrimPositions TrimWhitespaceASCII(const std::string& input, 1.315 + TrimPositions positions, 1.316 + std::string* output) { 1.317 + return TrimStringT(input, kWhitespaceASCII, positions, output); 1.318 +} 1.319 + 1.320 +// This function is only for backward-compatibility. 1.321 +// To be removed when all callers are updated. 1.322 +TrimPositions TrimWhitespace(const std::string& input, 1.323 + TrimPositions positions, 1.324 + std::string* output) { 1.325 + return TrimWhitespaceASCII(input, positions, output); 1.326 +} 1.327 + 1.328 +std::string WideToASCII(const std::wstring& wide) { 1.329 + DCHECK(IsStringASCII(wide)); 1.330 + return std::string(wide.begin(), wide.end()); 1.331 +} 1.332 + 1.333 +std::wstring ASCIIToWide(const std::string& ascii) { 1.334 + DCHECK(IsStringASCII(ascii)); 1.335 + return std::wstring(ascii.begin(), ascii.end()); 1.336 +} 1.337 + 1.338 +std::string UTF16ToASCII(const string16& utf16) { 1.339 + DCHECK(IsStringASCII(utf16)); 1.340 + return std::string(utf16.begin(), utf16.end()); 1.341 +} 1.342 + 1.343 +string16 ASCIIToUTF16(const std::string& ascii) { 1.344 + DCHECK(IsStringASCII(ascii)); 1.345 + return string16(ascii.begin(), ascii.end()); 1.346 +} 1.347 + 1.348 +template<class STR> 1.349 +static bool DoIsStringASCII(const STR& str) { 1.350 + for (size_t i = 0; i < str.length(); i++) { 1.351 + typename ToUnsigned<typename STR::value_type>::Unsigned c = str[i]; 1.352 + if (c > 0x7F) 1.353 + return false; 1.354 + } 1.355 + return true; 1.356 +} 1.357 + 1.358 +bool IsStringASCII(const std::wstring& str) { 1.359 + return DoIsStringASCII(str); 1.360 +} 1.361 + 1.362 +#if !defined(WCHAR_T_IS_UTF16) 1.363 +bool IsStringASCII(const string16& str) { 1.364 + return DoIsStringASCII(str); 1.365 +} 1.366 +#endif 1.367 + 1.368 +bool IsStringASCII(const std::string& str) { 1.369 + return DoIsStringASCII(str); 1.370 +} 1.371 + 1.372 +// Overloaded wrappers around vsnprintf and vswprintf. The buf_size parameter 1.373 +// is the size of the buffer. These return the number of characters in the 1.374 +// formatted string excluding the NUL terminator. If the buffer is not 1.375 +// large enough to accommodate the formatted string without truncation, they 1.376 +// return the number of characters that would be in the fully-formatted string 1.377 +// (vsnprintf, and vswprintf on Windows), or -1 (vswprintf on POSIX platforms). 1.378 +inline int vsnprintfT(char* buffer, 1.379 + size_t buf_size, 1.380 + const char* format, 1.381 + va_list argptr) { 1.382 + return base::vsnprintf(buffer, buf_size, format, argptr); 1.383 +} 1.384 + 1.385 +inline int vsnprintfT(wchar_t* buffer, 1.386 + size_t buf_size, 1.387 + const wchar_t* format, 1.388 + va_list argptr) { 1.389 + return base::vswprintf(buffer, buf_size, format, argptr); 1.390 +} 1.391 + 1.392 +// Templatized backend for StringPrintF/StringAppendF. This does not finalize 1.393 +// the va_list, the caller is expected to do that. 1.394 +template <class StringType> 1.395 +static void StringAppendVT(StringType* dst, 1.396 + const typename StringType::value_type* format, 1.397 + va_list ap) { 1.398 + // First try with a small fixed size buffer. 1.399 + // This buffer size should be kept in sync with StringUtilTest.GrowBoundary 1.400 + // and StringUtilTest.StringPrintfBounds. 1.401 + typename StringType::value_type stack_buf[1024]; 1.402 + 1.403 + va_list backup_ap; 1.404 + base_va_copy(backup_ap, ap); 1.405 + 1.406 +#if !defined(OS_WIN) 1.407 + errno = 0; 1.408 +#endif 1.409 + int result = vsnprintfT(stack_buf, arraysize(stack_buf), format, backup_ap); 1.410 + va_end(backup_ap); 1.411 + 1.412 + if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) { 1.413 + // It fit. 1.414 + dst->append(stack_buf, result); 1.415 + return; 1.416 + } 1.417 + 1.418 + // Repeatedly increase buffer size until it fits. 1.419 + int mem_length = arraysize(stack_buf); 1.420 + while (true) { 1.421 + if (result < 0) { 1.422 +#if !defined(OS_WIN) 1.423 + // On Windows, vsnprintfT always returns the number of characters in a 1.424 + // fully-formatted string, so if we reach this point, something else is 1.425 + // wrong and no amount of buffer-doubling is going to fix it. 1.426 + if (errno != 0 && errno != EOVERFLOW) 1.427 +#endif 1.428 + { 1.429 + // If an error other than overflow occurred, it's never going to work. 1.430 + DLOG(WARNING) << "Unable to printf the requested string due to error."; 1.431 + return; 1.432 + } 1.433 + // Try doubling the buffer size. 1.434 + mem_length *= 2; 1.435 + } else { 1.436 + // We need exactly "result + 1" characters. 1.437 + mem_length = result + 1; 1.438 + } 1.439 + 1.440 + if (mem_length > 32 * 1024 * 1024) { 1.441 + // That should be plenty, don't try anything larger. This protects 1.442 + // against huge allocations when using vsnprintfT implementations that 1.443 + // return -1 for reasons other than overflow without setting errno. 1.444 + DLOG(WARNING) << "Unable to printf the requested string due to size."; 1.445 + return; 1.446 + } 1.447 + 1.448 + std::vector<typename StringType::value_type> mem_buf(mem_length); 1.449 + 1.450 + // Restore the va_list before we use it again. 1.451 + base_va_copy(backup_ap, ap); 1.452 + 1.453 + result = vsnprintfT(&mem_buf[0], mem_length, format, ap); 1.454 + va_end(backup_ap); 1.455 + 1.456 + if ((result >= 0) && (result < mem_length)) { 1.457 + // It fit. 1.458 + dst->append(&mem_buf[0], result); 1.459 + return; 1.460 + } 1.461 + } 1.462 +} 1.463 + 1.464 +namespace { 1.465 + 1.466 +template <typename STR, typename INT, typename UINT, bool NEG> 1.467 +struct IntToStringT { 1.468 + 1.469 + // This is to avoid a compiler warning about unary minus on unsigned type. 1.470 + // For example, say you had the following code: 1.471 + // template <typename INT> 1.472 + // INT abs(INT value) { return value < 0 ? -value : value; } 1.473 + // Even though if INT is unsigned, it's impossible for value < 0, so the 1.474 + // unary minus will never be taken, the compiler will still generate a 1.475 + // warning. We do a little specialization dance... 1.476 + template <typename INT2, typename UINT2, bool NEG2> 1.477 + struct ToUnsignedT { }; 1.478 + 1.479 + template <typename INT2, typename UINT2> 1.480 + struct ToUnsignedT<INT2, UINT2, false> { 1.481 + static UINT2 ToUnsigned(INT2 value) { 1.482 + return static_cast<UINT2>(value); 1.483 + } 1.484 + }; 1.485 + 1.486 + template <typename INT2, typename UINT2> 1.487 + struct ToUnsignedT<INT2, UINT2, true> { 1.488 + static UINT2 ToUnsigned(INT2 value) { 1.489 + return static_cast<UINT2>(value < 0 ? -value : value); 1.490 + } 1.491 + }; 1.492 + 1.493 + // This set of templates is very similar to the above templates, but 1.494 + // for testing whether an integer is negative. 1.495 + template <typename INT2, bool NEG2> 1.496 + struct TestNegT {}; 1.497 + template <typename INT2> 1.498 + struct TestNegT<INT2, false> { 1.499 + static bool TestNeg(INT2 value) { 1.500 + // value is unsigned, and can never be negative. 1.501 + return false; 1.502 + } 1.503 + }; 1.504 + template <typename INT2> 1.505 + struct TestNegT<INT2, true> { 1.506 + static bool TestNeg(INT2 value) { 1.507 + return value < 0; 1.508 + } 1.509 + }; 1.510 + 1.511 + static STR IntToString(INT value) { 1.512 + // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. 1.513 + // So round up to allocate 3 output characters per byte, plus 1 for '-'. 1.514 + const int kOutputBufSize = 3 * sizeof(INT) + 1; 1.515 + 1.516 + // Allocate the whole string right away, we will right back to front, and 1.517 + // then return the substr of what we ended up using. 1.518 + STR outbuf(kOutputBufSize, 0); 1.519 + 1.520 + bool is_neg = TestNegT<INT, NEG>::TestNeg(value); 1.521 + // Even though is_neg will never be true when INT is parameterized as 1.522 + // unsigned, even the presence of the unary operation causes a warning. 1.523 + UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value); 1.524 + 1.525 + for (typename STR::iterator it = outbuf.end();;) { 1.526 + --it; 1.527 + DCHECK(it != outbuf.begin()); 1.528 + *it = static_cast<typename STR::value_type>((res % 10) + '0'); 1.529 + res /= 10; 1.530 + 1.531 + // We're done.. 1.532 + if (res == 0) { 1.533 + if (is_neg) { 1.534 + --it; 1.535 + DCHECK(it != outbuf.begin()); 1.536 + *it = static_cast<typename STR::value_type>('-'); 1.537 + } 1.538 + return STR(it, outbuf.end()); 1.539 + } 1.540 + } 1.541 + NOTREACHED(); 1.542 + return STR(); 1.543 + } 1.544 +}; 1.545 + 1.546 +} 1.547 + 1.548 +std::string IntToString(int value) { 1.549 + return IntToStringT<std::string, int, unsigned int, true>:: 1.550 + IntToString(value); 1.551 +} 1.552 +std::wstring IntToWString(int value) { 1.553 + return IntToStringT<std::wstring, int, unsigned int, true>:: 1.554 + IntToString(value); 1.555 +} 1.556 +std::string UintToString(unsigned int value) { 1.557 + return IntToStringT<std::string, unsigned int, unsigned int, false>:: 1.558 + IntToString(value); 1.559 +} 1.560 +std::wstring UintToWString(unsigned int value) { 1.561 + return IntToStringT<std::wstring, unsigned int, unsigned int, false>:: 1.562 + IntToString(value); 1.563 +} 1.564 +std::string Int64ToString(int64_t value) { 1.565 + return IntToStringT<std::string, int64_t, uint64_t, true>:: 1.566 + IntToString(value); 1.567 +} 1.568 +std::wstring Int64ToWString(int64_t value) { 1.569 + return IntToStringT<std::wstring, int64_t, uint64_t, true>:: 1.570 + IntToString(value); 1.571 +} 1.572 +std::string Uint64ToString(uint64_t value) { 1.573 + return IntToStringT<std::string, uint64_t, uint64_t, false>:: 1.574 + IntToString(value); 1.575 +} 1.576 +std::wstring Uint64ToWString(uint64_t value) { 1.577 + return IntToStringT<std::wstring, uint64_t, uint64_t, false>:: 1.578 + IntToString(value); 1.579 +} 1.580 + 1.581 +// Lower-level routine that takes a va_list and appends to a specified 1.582 +// string. All other routines are just convenience wrappers around it. 1.583 +static void StringAppendV(std::string* dst, const char* format, va_list ap) { 1.584 + StringAppendVT(dst, format, ap); 1.585 +} 1.586 + 1.587 +static void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) { 1.588 + StringAppendVT(dst, format, ap); 1.589 +} 1.590 + 1.591 +std::string StringPrintf(const char* format, ...) { 1.592 + va_list ap; 1.593 + va_start(ap, format); 1.594 + std::string result; 1.595 + StringAppendV(&result, format, ap); 1.596 + va_end(ap); 1.597 + return result; 1.598 +} 1.599 + 1.600 +std::wstring StringPrintf(const wchar_t* format, ...) { 1.601 + va_list ap; 1.602 + va_start(ap, format); 1.603 + std::wstring result; 1.604 + StringAppendV(&result, format, ap); 1.605 + va_end(ap); 1.606 + return result; 1.607 +} 1.608 + 1.609 +const std::string& SStringPrintf(std::string* dst, const char* format, ...) { 1.610 + va_list ap; 1.611 + va_start(ap, format); 1.612 + dst->clear(); 1.613 + StringAppendV(dst, format, ap); 1.614 + va_end(ap); 1.615 + return *dst; 1.616 +} 1.617 + 1.618 +const std::wstring& SStringPrintf(std::wstring* dst, 1.619 + const wchar_t* format, ...) { 1.620 + va_list ap; 1.621 + va_start(ap, format); 1.622 + dst->clear(); 1.623 + StringAppendV(dst, format, ap); 1.624 + va_end(ap); 1.625 + return *dst; 1.626 +} 1.627 + 1.628 +void StringAppendF(std::string* dst, const char* format, ...) { 1.629 + va_list ap; 1.630 + va_start(ap, format); 1.631 + StringAppendV(dst, format, ap); 1.632 + va_end(ap); 1.633 +} 1.634 + 1.635 +void StringAppendF(std::wstring* dst, const wchar_t* format, ...) { 1.636 + va_list ap; 1.637 + va_start(ap, format); 1.638 + StringAppendV(dst, format, ap); 1.639 + va_end(ap); 1.640 +} 1.641 + 1.642 +template<typename STR> 1.643 +static void SplitStringT(const STR& str, 1.644 + const typename STR::value_type s, 1.645 + bool trim_whitespace, 1.646 + std::vector<STR>* r) { 1.647 + size_t last = 0; 1.648 + size_t i; 1.649 + size_t c = str.size(); 1.650 + for (i = 0; i <= c; ++i) { 1.651 + if (i == c || str[i] == s) { 1.652 + size_t len = i - last; 1.653 + STR tmp = str.substr(last, len); 1.654 + if (trim_whitespace) { 1.655 + STR t_tmp; 1.656 + TrimWhitespace(tmp, TRIM_ALL, &t_tmp); 1.657 + r->push_back(t_tmp); 1.658 + } else { 1.659 + r->push_back(tmp); 1.660 + } 1.661 + last = i + 1; 1.662 + } 1.663 + } 1.664 +} 1.665 + 1.666 +void SplitString(const std::wstring& str, 1.667 + wchar_t s, 1.668 + std::vector<std::wstring>* r) { 1.669 + SplitStringT(str, s, true, r); 1.670 +} 1.671 + 1.672 +void SplitString(const std::string& str, 1.673 + char s, 1.674 + std::vector<std::string>* r) { 1.675 + SplitStringT(str, s, true, r); 1.676 +} 1.677 + 1.678 +// For the various *ToInt conversions, there are no *ToIntTraits classes to use 1.679 +// because there's no such thing as strtoi. Use *ToLongTraits through a cast 1.680 +// instead, requiring that long and int are compatible and equal-width. They 1.681 +// are on our target platforms. 1.682 + 1.683 +// XXX Sigh. 1.684 + 1.685 +#if !defined(ARCH_CPU_64_BITS) 1.686 +bool StringToInt(const std::string& input, int* output) { 1.687 + COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); 1.688 + return StringToNumber<StringToLongTraits>(input, 1.689 + reinterpret_cast<long*>(output)); 1.690 +} 1.691 + 1.692 +bool StringToInt(const string16& input, int* output) { 1.693 + COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); 1.694 + return StringToNumber<String16ToLongTraits>(input, 1.695 + reinterpret_cast<long*>(output)); 1.696 +} 1.697 + 1.698 +#else 1.699 +bool StringToInt(const std::string& input, int* output) { 1.700 + long tmp; 1.701 + bool ok = StringToNumber<StringToLongTraits>(input, &tmp); 1.702 + if (!ok || tmp > kint32max) { 1.703 + return false; 1.704 + } 1.705 + *output = static_cast<int>(tmp); 1.706 + return true; 1.707 +} 1.708 + 1.709 +bool StringToInt(const string16& input, int* output) { 1.710 + long tmp; 1.711 + bool ok = StringToNumber<String16ToLongTraits>(input, &tmp); 1.712 + if (!ok || tmp > kint32max) { 1.713 + return false; 1.714 + } 1.715 + *output = static_cast<int>(tmp); 1.716 + return true; 1.717 +} 1.718 +#endif // !defined(ARCH_CPU_64_BITS) 1.719 + 1.720 +bool StringToInt64(const std::string& input, int64_t* output) { 1.721 + return StringToNumber<StringToInt64Traits>(input, output); 1.722 +} 1.723 + 1.724 +bool StringToInt64(const string16& input, int64_t* output) { 1.725 + return StringToNumber<String16ToInt64Traits>(input, output); 1.726 +} 1.727 + 1.728 +int StringToInt(const std::string& value) { 1.729 + int result; 1.730 + StringToInt(value, &result); 1.731 + return result; 1.732 +} 1.733 + 1.734 +int StringToInt(const string16& value) { 1.735 + int result; 1.736 + StringToInt(value, &result); 1.737 + return result; 1.738 +} 1.739 + 1.740 +int64_t StringToInt64(const std::string& value) { 1.741 + int64_t result; 1.742 + StringToInt64(value, &result); 1.743 + return result; 1.744 +} 1.745 + 1.746 +int64_t StringToInt64(const string16& value) { 1.747 + int64_t result; 1.748 + StringToInt64(value, &result); 1.749 + return result; 1.750 +} 1.751 + 1.752 +// The following code is compatible with the OpenBSD lcpy interface. See: 1.753 +// http://www.gratisoft.us/todd/papers/strlcpy.html 1.754 +// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c 1.755 + 1.756 +namespace { 1.757 + 1.758 +template <typename CHAR> 1.759 +size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { 1.760 + for (size_t i = 0; i < dst_size; ++i) { 1.761 + if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. 1.762 + return i; 1.763 + } 1.764 + 1.765 + // We were left off at dst_size. We over copied 1 byte. Null terminate. 1.766 + if (dst_size != 0) 1.767 + dst[dst_size - 1] = 0; 1.768 + 1.769 + // Count the rest of the |src|, and return it's length in characters. 1.770 + while (src[dst_size]) ++dst_size; 1.771 + return dst_size; 1.772 +} 1.773 + 1.774 +} // namespace 1.775 + 1.776 +size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { 1.777 + return lcpyT<char>(dst, src, dst_size); 1.778 +} 1.779 +size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { 1.780 + return lcpyT<wchar_t>(dst, src, dst_size); 1.781 +}