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