ipc/chromium/src/base/string_util.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
     5 #include "base/string_util.h"
     7 #include "build/build_config.h"
     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>
    20 #include <algorithm>
    21 #include <vector>
    23 #include "base/basictypes.h"
    24 #include "base/logging.h"
    25 #include "base/singleton.h"
    27 namespace {
    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 };
    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 };
    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 };
    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;
    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;
    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 }
   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 };
   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 };
   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 };
   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 };
   188 }  // namespace
   191 namespace base {
   193 bool IsWprintfFormatPortable(const wchar_t* format) {
   194   for (const wchar_t* position = format; *position != '\0'; ++position) {
   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         }
   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         }
   218         if (wcschr(L"diouxXeEfgGaAcspn%", *position)) {
   219           // Portable, keep scanning the rest of the format string.
   220           in_specification = false;
   221         }
   222       }
   223     }
   225   }
   227   return true;
   228 }
   231 }  // namespace base
   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 };
   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;
   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   }
   295   // Trim the whitespace.
   296   *output =
   297       input.substr(first_good_char, last_good_char - first_good_char + 1);
   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 }
   305 TrimPositions TrimWhitespace(const std::wstring& input,
   306                              TrimPositions positions,
   307                              std::wstring* output) {
   308   return TrimStringT(input, kWhitespaceWide, positions, output);
   309 }
   311 TrimPositions TrimWhitespaceASCII(const std::string& input,
   312                                   TrimPositions positions,
   313                                   std::string* output) {
   314   return TrimStringT(input, kWhitespaceASCII, positions, output);
   315 }
   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 }
   325 std::string WideToASCII(const std::wstring& wide) {
   326   DCHECK(IsStringASCII(wide));
   327   return std::string(wide.begin(), wide.end());
   328 }
   330 std::wstring ASCIIToWide(const std::string& ascii) {
   331   DCHECK(IsStringASCII(ascii));
   332   return std::wstring(ascii.begin(), ascii.end());
   333 }
   335 std::string UTF16ToASCII(const string16& utf16) {
   336   DCHECK(IsStringASCII(utf16));
   337   return std::string(utf16.begin(), utf16.end());
   338 }
   340 string16 ASCIIToUTF16(const std::string& ascii) {
   341   DCHECK(IsStringASCII(ascii));
   342   return string16(ascii.begin(), ascii.end());
   343 }
   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 }
   355 bool IsStringASCII(const std::wstring& str) {
   356   return DoIsStringASCII(str);
   357 }
   359 #if !defined(WCHAR_T_IS_UTF16)
   360 bool IsStringASCII(const string16& str) {
   361   return DoIsStringASCII(str);
   362 }
   363 #endif
   365 bool IsStringASCII(const std::string& str) {
   366   return DoIsStringASCII(str);
   367 }
   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 }
   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 }
   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];
   400   va_list backup_ap;
   401   base_va_copy(backup_ap, ap);
   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);
   409   if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) {
   410     // It fit.
   411     dst->append(stack_buf, result);
   412     return;
   413   }
   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     }
   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     }
   445     std::vector<typename StringType::value_type> mem_buf(mem_length);
   447     // Restore the va_list before we use it again.
   448     base_va_copy(backup_ap, ap);
   450     result = vsnprintfT(&mem_buf[0], mem_length, format, ap);
   451     va_end(backup_ap);
   453     if ((result >= 0) && (result < mem_length)) {
   454       // It fit.
   455       dst->append(&mem_buf[0], result);
   456       return;
   457     }
   458   }
   459 }
   461 namespace {
   463 template <typename STR, typename INT, typename UINT, bool NEG>
   464 struct IntToStringT {
   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 { };
   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   };
   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   };
   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   };
   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;
   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);
   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);
   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;
   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 };
   543 }
   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 }
   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 }
   584 static void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) {
   585   StringAppendVT(dst, format, ap);
   586 }
   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 }
   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 }
   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 }
   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 }
   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 }
   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 }
   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 }
   663 void SplitString(const std::wstring& str,
   664                  wchar_t s,
   665                  std::vector<std::wstring>* r) {
   666   SplitStringT(str, s, true, r);
   667 }
   669 void SplitString(const std::string& str,
   670                  char s,
   671                  std::vector<std::string>* r) {
   672   SplitStringT(str, s, true, r);
   673 }
   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.
   680 // XXX Sigh.
   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 }
   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 }
   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 }
   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)
   717 bool StringToInt64(const std::string& input, int64_t* output) {
   718   return StringToNumber<StringToInt64Traits>(input, output);
   719 }
   721 bool StringToInt64(const string16& input, int64_t* output) {
   722   return StringToNumber<String16ToInt64Traits>(input, output);
   723 }
   725 int StringToInt(const std::string& value) {
   726   int result;
   727   StringToInt(value, &result);
   728   return result;
   729 }
   731 int StringToInt(const string16& value) {
   732   int result;
   733   StringToInt(value, &result);
   734   return result;
   735 }
   737 int64_t StringToInt64(const std::string& value) {
   738   int64_t result;
   739   StringToInt64(value, &result);
   740   return result;
   741 }
   743 int64_t StringToInt64(const string16& value) {
   744   int64_t result;
   745   StringToInt64(value, &result);
   746   return result;
   747 }
   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
   753 namespace {
   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   }
   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;
   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 }
   771 }  // namespace
   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 }

mercurial