LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - string_util.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 43 270 15.9 %
Date: 2017-07-14 16:53:18 Functions: 8 88 9.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13