• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/string_number_conversions.h"
6 
7 #include <errno.h>
8 #include <stdlib.h>
9 
10 #include <limits>
11 
12 #include "base/logging.h"
13 #include "base/third_party/dmg_fp/dmg_fp.h"
14 #include "base/utf_string_conversions.h"
15 
16 namespace base {
17 
18 namespace {
19 
20 template <typename STR, typename INT, typename UINT, bool NEG>
21 struct IntToStringT {
22   // This is to avoid a compiler warning about unary minus on unsigned type.
23   // For example, say you had the following code:
24   //   template <typename INT>
25   //   INT abs(INT value) { return value < 0 ? -value : value; }
26   // Even though if INT is unsigned, it's impossible for value < 0, so the
27   // unary minus will never be taken, the compiler will still generate a
28   // warning.  We do a little specialization dance...
29   template <typename INT2, typename UINT2, bool NEG2>
30   struct ToUnsignedT {};
31 
32   template <typename INT2, typename UINT2>
33   struct ToUnsignedT<INT2, UINT2, false> {
ToUnsignedbase::__anonf7baffdf0111::IntToStringT::ToUnsignedT34     static UINT2 ToUnsigned(INT2 value) {
35       return static_cast<UINT2>(value);
36     }
37   };
38 
39   template <typename INT2, typename UINT2>
40   struct ToUnsignedT<INT2, UINT2, true> {
ToUnsignedbase::__anonf7baffdf0111::IntToStringT::ToUnsignedT41     static UINT2 ToUnsigned(INT2 value) {
42       return static_cast<UINT2>(value < 0 ? -value : value);
43     }
44   };
45 
46   // This set of templates is very similar to the above templates, but
47   // for testing whether an integer is negative.
48   template <typename INT2, bool NEG2>
49   struct TestNegT {};
50   template <typename INT2>
51   struct TestNegT<INT2, false> {
TestNegbase::__anonf7baffdf0111::IntToStringT::TestNegT52     static bool TestNeg(INT2 value) {
53       // value is unsigned, and can never be negative.
54       return false;
55     }
56   };
57   template <typename INT2>
58   struct TestNegT<INT2, true> {
TestNegbase::__anonf7baffdf0111::IntToStringT::TestNegT59     static bool TestNeg(INT2 value) {
60       return value < 0;
61     }
62   };
63 
IntToStringbase::__anonf7baffdf0111::IntToStringT64   static STR IntToString(INT value) {
65     // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4.
66     // So round up to allocate 3 output characters per byte, plus 1 for '-'.
67     const int kOutputBufSize = 3 * sizeof(INT) + 1;
68 
69     // Allocate the whole string right away, we will right back to front, and
70     // then return the substr of what we ended up using.
71     STR outbuf(kOutputBufSize, 0);
72 
73     bool is_neg = TestNegT<INT, NEG>::TestNeg(value);
74     // Even though is_neg will never be true when INT is parameterized as
75     // unsigned, even the presence of the unary operation causes a warning.
76     UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value);
77 
78     for (typename STR::iterator it = outbuf.end();;) {
79       --it;
80       DCHECK(it != outbuf.begin());
81       *it = static_cast<typename STR::value_type>((res % 10) + '0');
82       res /= 10;
83 
84       // We're done..
85       if (res == 0) {
86         if (is_neg) {
87           --it;
88           DCHECK(it != outbuf.begin());
89           *it = static_cast<typename STR::value_type>('-');
90         }
91         return STR(it, outbuf.end());
92       }
93     }
94     NOTREACHED();
95     return STR();
96   }
97 };
98 
99 // Utility to convert a character to a digit in a given base
100 template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit {
101 };
102 
103 // Faster specialization for bases <= 10
104 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
105  public:
Convert(CHAR c,uint8 * digit)106   static bool Convert(CHAR c, uint8* digit) {
107     if (c >= '0' && c < '0' + BASE) {
108       *digit = c - '0';
109       return true;
110     }
111     return false;
112   }
113 };
114 
115 // Specialization for bases where 10 < base <= 36
116 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
117  public:
Convert(CHAR c,uint8 * digit)118   static bool Convert(CHAR c, uint8* digit) {
119     if (c >= '0' && c <= '9') {
120       *digit = c - '0';
121     } else if (c >= 'a' && c < 'a' + BASE - 10) {
122       *digit = c - 'a' + 10;
123     } else if (c >= 'A' && c < 'A' + BASE - 10) {
124       *digit = c - 'A' + 10;
125     } else {
126       return false;
127     }
128     return true;
129   }
130 };
131 
CharToDigit(CHAR c,uint8 * digit)132 template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) {
133   return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit);
134 }
135 
136 // There is an IsWhitespace for wchars defined in string_util.h, but it is
137 // locale independent, whereas the functions we are replacing were
138 // locale-dependent. TBD what is desired, but for the moment let's not introduce
139 // a change in behaviour.
140 template<typename CHAR> class WhitespaceHelper {
141 };
142 
143 template<> class WhitespaceHelper<char> {
144  public:
Invoke(char c)145   static bool Invoke(char c) {
146     return 0 != isspace(static_cast<unsigned char>(c));
147   }
148 };
149 
150 template<> class WhitespaceHelper<char16> {
151  public:
Invoke(char16 c)152   static bool Invoke(char16 c) {
153     return 0 != iswspace(c);
154   }
155 };
156 
LocalIsWhitespace(CHAR c)157 template<typename CHAR> bool LocalIsWhitespace(CHAR c) {
158   return WhitespaceHelper<CHAR>::Invoke(c);
159 }
160 
161 // IteratorRangeToNumberTraits should provide:
162 //  - a typedef for iterator_type, the iterator type used as input.
163 //  - a typedef for value_type, the target numeric type.
164 //  - static functions min, max (returning the minimum and maximum permitted
165 //    values)
166 //  - constant kBase, the base in which to interpret the input
167 template<typename IteratorRangeToNumberTraits>
168 class IteratorRangeToNumber {
169  public:
170   typedef IteratorRangeToNumberTraits traits;
171   typedef typename traits::iterator_type const_iterator;
172   typedef typename traits::value_type value_type;
173 
174   // Generalized iterator-range-to-number conversion.
175   //
Invoke(const_iterator begin,const_iterator end,value_type * output)176   static bool Invoke(const_iterator begin,
177                      const_iterator end,
178                      value_type* output) {
179     bool valid = true;
180 
181     while (begin != end && LocalIsWhitespace(*begin)) {
182       valid = false;
183       ++begin;
184     }
185 
186     if (begin != end && *begin == '-') {
187       if (!Negative::Invoke(begin + 1, end, output)) {
188         valid = false;
189       }
190     } else {
191       if (begin != end && *begin == '+') {
192         ++begin;
193       }
194       if (!Positive::Invoke(begin, end, output)) {
195         valid = false;
196       }
197     }
198 
199     return valid;
200   }
201 
202  private:
203   // Sign provides:
204   //  - a static function, CheckBounds, that determines whether the next digit
205   //    causes an overflow/underflow
206   //  - a static function, Increment, that appends the next digit appropriately
207   //    according to the sign of the number being parsed.
208   template<typename Sign>
209   class Base {
210    public:
Invoke(const_iterator begin,const_iterator end,typename traits::value_type * output)211     static bool Invoke(const_iterator begin, const_iterator end,
212                        typename traits::value_type* output) {
213       *output = 0;
214 
215       if (begin == end) {
216         return false;
217       }
218 
219       // Note: no performance difference was found when using template
220       // specialization to remove this check in bases other than 16
221       if (traits::kBase == 16 && end - begin >= 2 && *begin == '0' &&
222           (*(begin + 1) == 'x' || *(begin + 1) == 'X')) {
223         begin += 2;
224       }
225 
226       for (const_iterator current = begin; current != end; ++current) {
227         uint8 new_digit = 0;
228 
229         if (!CharToDigit<traits::kBase>(*current, &new_digit)) {
230           return false;
231         }
232 
233         if (current != begin) {
234           if (!Sign::CheckBounds(output, new_digit)) {
235             return false;
236           }
237           *output *= traits::kBase;
238         }
239 
240         Sign::Increment(new_digit, output);
241       }
242       return true;
243     }
244   };
245 
246   class Positive : public Base<Positive> {
247    public:
CheckBounds(value_type * output,uint8 new_digit)248     static bool CheckBounds(value_type* output, uint8 new_digit) {
249       if (*output > static_cast<value_type>(traits::max() / traits::kBase) ||
250           (*output == static_cast<value_type>(traits::max() / traits::kBase) &&
251            new_digit > traits::max() % traits::kBase)) {
252         *output = traits::max();
253         return false;
254       }
255       return true;
256     }
Increment(uint8 increment,value_type * output)257     static void Increment(uint8 increment, value_type* output) {
258       *output += increment;
259     }
260   };
261 
262   class Negative : public Base<Negative> {
263    public:
CheckBounds(value_type * output,uint8 new_digit)264     static bool CheckBounds(value_type* output, uint8 new_digit) {
265       if (*output < traits::min() / traits::kBase ||
266           (*output == traits::min() / traits::kBase &&
267            new_digit > 0 - traits::min() % traits::kBase)) {
268         *output = traits::min();
269         return false;
270       }
271       return true;
272     }
Increment(uint8 increment,value_type * output)273     static void Increment(uint8 increment, value_type* output) {
274       *output -= increment;
275     }
276   };
277 };
278 
279 template<typename ITERATOR, typename VALUE, int BASE>
280 class BaseIteratorRangeToNumberTraits {
281  public:
282   typedef ITERATOR iterator_type;
283   typedef VALUE value_type;
min()284   static value_type min() {
285     return std::numeric_limits<value_type>::min();
286   }
max()287   static value_type max() {
288     return std::numeric_limits<value_type>::max();
289   }
290   static const int kBase = BASE;
291 };
292 
293 typedef BaseIteratorRangeToNumberTraits<std::string::const_iterator, int, 10>
294     IteratorRangeToIntTraits;
295 typedef BaseIteratorRangeToNumberTraits<string16::const_iterator, int, 10>
296     WideIteratorRangeToIntTraits;
297 typedef BaseIteratorRangeToNumberTraits<std::string::const_iterator, int64, 10>
298     IteratorRangeToInt64Traits;
299 typedef BaseIteratorRangeToNumberTraits<string16::const_iterator, int64, 10>
300     WideIteratorRangeToInt64Traits;
301 
302 typedef BaseIteratorRangeToNumberTraits<const char*, int, 10>
303     CharBufferToIntTraits;
304 typedef BaseIteratorRangeToNumberTraits<const char16*, int, 10>
305     WideCharBufferToIntTraits;
306 typedef BaseIteratorRangeToNumberTraits<const char*, int64, 10>
307     CharBufferToInt64Traits;
308 typedef BaseIteratorRangeToNumberTraits<const char16*, int64, 10>
309     WideCharBufferToInt64Traits;
310 
311 template<typename ITERATOR>
312 class BaseHexIteratorRangeToIntTraits
313     : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> {
314  public:
315   // Allow parsing of 0xFFFFFFFF, which is technically an overflow
max()316   static unsigned int max() {
317     return std::numeric_limits<unsigned int>::max();
318   }
319 };
320 
321 typedef BaseHexIteratorRangeToIntTraits<std::string::const_iterator>
322     HexIteratorRangeToIntTraits;
323 typedef BaseHexIteratorRangeToIntTraits<const char*>
324     HexCharBufferToIntTraits;
325 
326 template<typename STR>
HexStringToBytesT(const STR & input,std::vector<uint8> * output)327 bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) {
328   DCHECK_EQ(output->size(), 0u);
329   size_t count = input.size();
330   if (count == 0 || (count % 2) != 0)
331     return false;
332   for (uintptr_t i = 0; i < count / 2; ++i) {
333     uint8 msb = 0;  // most significant 4 bits
334     uint8 lsb = 0;  // least significant 4 bits
335     if (!CharToDigit<16>(input[i * 2], &msb) ||
336         !CharToDigit<16>(input[i * 2 + 1], &lsb))
337       return false;
338     output->push_back((msb << 4) | lsb);
339   }
340   return true;
341 }
342 
343 }  // namespace
344 
IntToString(int value)345 std::string IntToString(int value) {
346   return IntToStringT<std::string, int, unsigned int, true>::
347       IntToString(value);
348 }
349 
IntToString16(int value)350 string16 IntToString16(int value) {
351   return IntToStringT<string16, int, unsigned int, true>::
352       IntToString(value);
353 }
354 
UintToString(unsigned int value)355 std::string UintToString(unsigned int value) {
356   return IntToStringT<std::string, unsigned int, unsigned int, false>::
357       IntToString(value);
358 }
359 
UintToString16(unsigned int value)360 string16 UintToString16(unsigned int value) {
361   return IntToStringT<string16, unsigned int, unsigned int, false>::
362       IntToString(value);
363 }
364 
Int64ToString(int64 value)365 std::string Int64ToString(int64 value) {
366   return IntToStringT<std::string, int64, uint64, true>::
367       IntToString(value);
368 }
369 
Int64ToString16(int64 value)370 string16 Int64ToString16(int64 value) {
371   return IntToStringT<string16, int64, uint64, true>::IntToString(value);
372 }
373 
Uint64ToString(uint64 value)374 std::string Uint64ToString(uint64 value) {
375   return IntToStringT<std::string, uint64, uint64, false>::
376       IntToString(value);
377 }
378 
Uint64ToString16(uint64 value)379 string16 Uint64ToString16(uint64 value) {
380   return IntToStringT<string16, uint64, uint64, false>::
381       IntToString(value);
382 }
383 
DoubleToString(double value)384 std::string DoubleToString(double value) {
385   // According to g_fmt.cc, it is sufficient to declare a buffer of size 32.
386   char buffer[32];
387   dmg_fp::g_fmt(buffer, value);
388   return std::string(buffer);
389 }
390 
StringToInt(const std::string & input,int * output)391 bool StringToInt(const std::string& input, int* output) {
392   return IteratorRangeToNumber<IteratorRangeToIntTraits>::Invoke(input.begin(),
393                                                                  input.end(),
394                                                                  output);
395 }
396 
397 #if !defined(ANDROID)
StringToInt(std::string::const_iterator begin,std::string::const_iterator end,int * output)398 bool StringToInt(std::string::const_iterator begin,
399                  std::string::const_iterator end,
400                  int* output) {
401   return IteratorRangeToNumber<IteratorRangeToIntTraits>::Invoke(begin,
402                                                                  end,
403                                                                  output);
404 }
405 #endif
406 
StringToInt(const char * begin,const char * end,int * output)407 bool StringToInt(const char* begin, const char* end, int* output) {
408   return IteratorRangeToNumber<CharBufferToIntTraits>::Invoke(begin,
409                                                               end,
410                                                               output);
411 }
412 
StringToInt(const string16 & input,int * output)413 bool StringToInt(const string16& input, int* output) {
414   return IteratorRangeToNumber<WideIteratorRangeToIntTraits>::Invoke(
415     input.begin(), input.end(), output);
416 }
417 
418 #if !defined(ANDROID)
StringToInt(string16::const_iterator begin,string16::const_iterator end,int * output)419 bool StringToInt(string16::const_iterator begin,
420                  string16::const_iterator end,
421                  int* output) {
422   return IteratorRangeToNumber<WideIteratorRangeToIntTraits>::Invoke(begin,
423                                                                      end,
424                                                                      output);
425 }
426 #endif
427 
StringToInt(const char16 * begin,const char16 * end,int * output)428 bool StringToInt(const char16* begin, const char16* end, int* output) {
429   return IteratorRangeToNumber<WideCharBufferToIntTraits>::Invoke(begin,
430                                                                   end,
431                                                                   output);
432 }
433 
StringToInt64(const std::string & input,int64 * output)434 bool StringToInt64(const std::string& input, int64* output) {
435   return IteratorRangeToNumber<IteratorRangeToInt64Traits>::Invoke(
436     input.begin(), input.end(), output);
437 }
438 
439 #if !defined(ANDROID)
StringToInt64(std::string::const_iterator begin,std::string::const_iterator end,int64 * output)440 bool StringToInt64(std::string::const_iterator begin,
441                  std::string::const_iterator end,
442                  int64* output) {
443   return IteratorRangeToNumber<IteratorRangeToInt64Traits>::Invoke(begin,
444                                                                  end,
445                                                                  output);
446 }
447 #endif
448 
StringToInt64(const char * begin,const char * end,int64 * output)449 bool StringToInt64(const char* begin, const char* end, int64* output) {
450   return IteratorRangeToNumber<CharBufferToInt64Traits>::Invoke(begin,
451                                                               end,
452                                                               output);
453 }
454 
StringToInt64(const string16 & input,int64 * output)455 bool StringToInt64(const string16& input, int64* output) {
456   return IteratorRangeToNumber<WideIteratorRangeToInt64Traits>::Invoke(
457     input.begin(), input.end(), output);
458 }
459 
460 #if !defined(ANDROID)
StringToInt64(string16::const_iterator begin,string16::const_iterator end,int64 * output)461 bool StringToInt64(string16::const_iterator begin,
462                  string16::const_iterator end,
463                  int64* output) {
464   return IteratorRangeToNumber<WideIteratorRangeToInt64Traits>::Invoke(begin,
465                                                                      end,
466                                                                      output);
467 }
468 #endif
469 
StringToInt64(const char16 * begin,const char16 * end,int64 * output)470 bool StringToInt64(const char16* begin, const char16* end, int64* output) {
471   return IteratorRangeToNumber<WideCharBufferToInt64Traits>::Invoke(begin,
472                                                                   end,
473                                                                   output);
474 }
475 
StringToDouble(const std::string & input,double * output)476 bool StringToDouble(const std::string& input, double* output) {
477   errno = 0;  // Thread-safe?  It is on at least Mac, Linux, and Windows.
478   char* endptr = NULL;
479   *output = dmg_fp::strtod(input.c_str(), &endptr);
480 
481   // Cases to return false:
482   //  - If errno is ERANGE, there was an overflow or underflow.
483   //  - If the input string is empty, there was nothing to parse.
484   //  - If endptr does not point to the end of the string, there are either
485   //    characters remaining in the string after a parsed number, or the string
486   //    does not begin with a parseable number.  endptr is compared to the
487   //    expected end given the string's stated length to correctly catch cases
488   //    where the string contains embedded NUL characters.
489   //  - If the first character is a space, there was leading whitespace
490   return errno == 0 &&
491          !input.empty() &&
492          input.c_str() + input.length() == endptr &&
493          !isspace(input[0]);
494 }
495 
496 // Note: if you need to add String16ToDouble, first ask yourself if it's
497 // really necessary. If it is, probably the best implementation here is to
498 // convert to 8-bit and then use the 8-bit version.
499 
500 // Note: if you need to add an iterator range version of StringToDouble, first
501 // ask yourself if it's really necessary. If it is, probably the best
502 // implementation here is to instantiate a string and use the string version.
503 
HexEncode(const void * bytes,size_t size)504 std::string HexEncode(const void* bytes, size_t size) {
505   static const char kHexChars[] = "0123456789ABCDEF";
506 
507   // Each input byte creates two output hex characters.
508   std::string ret(size * 2, '\0');
509 
510   for (size_t i = 0; i < size; ++i) {
511     char b = reinterpret_cast<const char*>(bytes)[i];
512     ret[(i * 2)] = kHexChars[(b >> 4) & 0xf];
513     ret[(i * 2) + 1] = kHexChars[b & 0xf];
514   }
515   return ret;
516 }
517 
HexStringToInt(const std::string & input,int * output)518 bool HexStringToInt(const std::string& input, int* output) {
519   return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke(
520     input.begin(), input.end(), output);
521 }
522 
523 #if !defined(ANDROID)
HexStringToInt(std::string::const_iterator begin,std::string::const_iterator end,int * output)524 bool HexStringToInt(std::string::const_iterator begin,
525                     std::string::const_iterator end,
526                     int* output) {
527   return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke(begin,
528                                                                     end,
529                                                                     output);
530 }
531 #endif
532 
HexStringToInt(const char * begin,const char * end,int * output)533 bool HexStringToInt(const char* begin, const char* end, int* output) {
534   return IteratorRangeToNumber<HexCharBufferToIntTraits>::Invoke(begin,
535                                                                     end,
536                                                                     output);
537 }
538 
HexStringToBytes(const std::string & input,std::vector<uint8> * output)539 bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) {
540   return HexStringToBytesT(input, output);
541 }
542 
543 }  // namespace base
544 
545