OLD | NEW |
(Empty) | |
| 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 "base/logging.h" |
| 11 #include "base/third_party/dmg_fp/dmg_fp.h" |
| 12 #include "base/utf_string_conversions.h" |
| 13 |
| 14 namespace base { |
| 15 |
| 16 namespace { |
| 17 |
| 18 template <typename STR, typename INT, typename UINT, bool NEG> |
| 19 struct IntToStringT { |
| 20 // This is to avoid a compiler warning about unary minus on unsigned type. |
| 21 // For example, say you had the following code: |
| 22 // template <typename INT> |
| 23 // INT abs(INT value) { return value < 0 ? -value : value; } |
| 24 // Even though if INT is unsigned, it's impossible for value < 0, so the |
| 25 // unary minus will never be taken, the compiler will still generate a |
| 26 // warning. We do a little specialization dance... |
| 27 template <typename INT2, typename UINT2, bool NEG2> |
| 28 struct ToUnsignedT {}; |
| 29 |
| 30 template <typename INT2, typename UINT2> |
| 31 struct ToUnsignedT<INT2, UINT2, false> { |
| 32 static UINT2 ToUnsigned(INT2 value) { |
| 33 return static_cast<UINT2>(value); |
| 34 } |
| 35 }; |
| 36 |
| 37 template <typename INT2, typename UINT2> |
| 38 struct ToUnsignedT<INT2, UINT2, true> { |
| 39 static UINT2 ToUnsigned(INT2 value) { |
| 40 return static_cast<UINT2>(value < 0 ? -value : value); |
| 41 } |
| 42 }; |
| 43 |
| 44 // This set of templates is very similar to the above templates, but |
| 45 // for testing whether an integer is negative. |
| 46 template <typename INT2, bool NEG2> |
| 47 struct TestNegT {}; |
| 48 template <typename INT2> |
| 49 struct TestNegT<INT2, false> { |
| 50 static bool TestNeg(INT2 value) { |
| 51 // value is unsigned, and can never be negative. |
| 52 return false; |
| 53 } |
| 54 }; |
| 55 template <typename INT2> |
| 56 struct TestNegT<INT2, true> { |
| 57 static bool TestNeg(INT2 value) { |
| 58 return value < 0; |
| 59 } |
| 60 }; |
| 61 |
| 62 static STR IntToString(INT value) { |
| 63 // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. |
| 64 // So round up to allocate 3 output characters per byte, plus 1 for '-'. |
| 65 const int kOutputBufSize = 3 * sizeof(INT) + 1; |
| 66 |
| 67 // Allocate the whole string right away, we will right back to front, and |
| 68 // then return the substr of what we ended up using. |
| 69 STR outbuf(kOutputBufSize, 0); |
| 70 |
| 71 bool is_neg = TestNegT<INT, NEG>::TestNeg(value); |
| 72 // Even though is_neg will never be true when INT is parameterized as |
| 73 // unsigned, even the presence of the unary operation causes a warning. |
| 74 UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value); |
| 75 |
| 76 for (typename STR::iterator it = outbuf.end();;) { |
| 77 --it; |
| 78 DCHECK(it != outbuf.begin()); |
| 79 *it = static_cast<typename STR::value_type>((res % 10) + '0'); |
| 80 res /= 10; |
| 81 |
| 82 // We're done.. |
| 83 if (res == 0) { |
| 84 if (is_neg) { |
| 85 --it; |
| 86 DCHECK(it != outbuf.begin()); |
| 87 *it = static_cast<typename STR::value_type>('-'); |
| 88 } |
| 89 return STR(it, outbuf.end()); |
| 90 } |
| 91 } |
| 92 NOTREACHED(); |
| 93 return STR(); |
| 94 } |
| 95 }; |
| 96 |
| 97 // Generalized string-to-number conversion. |
| 98 // |
| 99 // StringToNumberTraits should provide: |
| 100 // - a typedef for string_type, the STL string type used as input. |
| 101 // - a typedef for value_type, the target numeric type. |
| 102 // - a static function, convert_func, which dispatches to an appropriate |
| 103 // strtol-like function and returns type value_type. |
| 104 // - a static function, valid_func, which validates |input| and returns a bool |
| 105 // indicating whether it is in proper form. This is used to check for |
| 106 // conditions that convert_func tolerates but should result in |
| 107 // StringToNumber returning false. For strtol-like funtions, valid_func |
| 108 // should check for leading whitespace. |
| 109 template<typename StringToNumberTraits> |
| 110 bool StringToNumber(const typename StringToNumberTraits::string_type& input, |
| 111 typename StringToNumberTraits::value_type* output) { |
| 112 typedef StringToNumberTraits traits; |
| 113 |
| 114 errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. |
| 115 typename traits::string_type::value_type* endptr = NULL; |
| 116 typename traits::value_type value = traits::convert_func(input.c_str(), |
| 117 &endptr); |
| 118 *output = value; |
| 119 |
| 120 // Cases to return false: |
| 121 // - If errno is ERANGE, there was an overflow or underflow. |
| 122 // - If the input string is empty, there was nothing to parse. |
| 123 // - If endptr does not point to the end of the string, there are either |
| 124 // characters remaining in the string after a parsed number, or the string |
| 125 // does not begin with a parseable number. endptr is compared to the |
| 126 // expected end given the string's stated length to correctly catch cases |
| 127 // where the string contains embedded NUL characters. |
| 128 // - valid_func determines that the input is not in preferred form. |
| 129 return errno == 0 && |
| 130 !input.empty() && |
| 131 input.c_str() + input.length() == endptr && |
| 132 traits::valid_func(input); |
| 133 } |
| 134 |
| 135 static int strtoi(const char *nptr, char **endptr, int base) { |
| 136 long res = strtol(nptr, endptr, base); |
| 137 #if __LP64__ |
| 138 // Long is 64-bits, we have to handle under/overflow ourselves. |
| 139 if (res > kint32max) { |
| 140 res = kint32max; |
| 141 errno = ERANGE; |
| 142 } else if (res < kint32min) { |
| 143 res = kint32min; |
| 144 errno = ERANGE; |
| 145 } |
| 146 #endif |
| 147 return static_cast<int>(res); |
| 148 } |
| 149 |
| 150 static unsigned int strtoui(const char *nptr, char **endptr, int base) { |
| 151 unsigned long res = strtoul(nptr, endptr, base); |
| 152 #if __LP64__ |
| 153 // Long is 64-bits, we have to handle under/overflow ourselves. Test to see |
| 154 // if the result can fit into 32-bits (as signed or unsigned). |
| 155 if (static_cast<int>(static_cast<long>(res)) != static_cast<long>(res) && |
| 156 static_cast<unsigned int>(res) != res) { |
| 157 res = kuint32max; |
| 158 errno = ERANGE; |
| 159 } |
| 160 #endif |
| 161 return static_cast<unsigned int>(res); |
| 162 } |
| 163 |
| 164 class StringToIntTraits { |
| 165 public: |
| 166 typedef std::string string_type; |
| 167 typedef int value_type; |
| 168 static const int kBase = 10; |
| 169 static inline value_type convert_func(const string_type::value_type* str, |
| 170 string_type::value_type** endptr) { |
| 171 return strtoi(str, endptr, kBase); |
| 172 } |
| 173 static inline bool valid_func(const string_type& str) { |
| 174 return !str.empty() && !isspace(str[0]); |
| 175 } |
| 176 }; |
| 177 |
| 178 class String16ToIntTraits { |
| 179 public: |
| 180 typedef string16 string_type; |
| 181 typedef int value_type; |
| 182 static const int kBase = 10; |
| 183 static inline value_type convert_func(const string_type::value_type* str, |
| 184 string_type::value_type** endptr) { |
| 185 #if defined(WCHAR_T_IS_UTF16) |
| 186 return wcstol(str, endptr, kBase); |
| 187 #elif defined(WCHAR_T_IS_UTF32) |
| 188 std::string ascii_string = UTF16ToUTF8(string16(str)); |
| 189 char* ascii_end = NULL; |
| 190 value_type ret = strtoi(ascii_string.c_str(), &ascii_end, kBase); |
| 191 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
| 192 *endptr = |
| 193 const_cast<string_type::value_type*>(str) + ascii_string.length(); |
| 194 } |
| 195 return ret; |
| 196 #endif |
| 197 } |
| 198 static inline bool valid_func(const string_type& str) { |
| 199 return !str.empty() && !iswspace(str[0]); |
| 200 } |
| 201 }; |
| 202 |
| 203 class StringToInt64Traits { |
| 204 public: |
| 205 typedef std::string string_type; |
| 206 typedef int64 value_type; |
| 207 static const int kBase = 10; |
| 208 static inline value_type convert_func(const string_type::value_type* str, |
| 209 string_type::value_type** endptr) { |
| 210 #ifdef OS_WIN |
| 211 return _strtoi64(str, endptr, kBase); |
| 212 #else // assume OS_POSIX |
| 213 return strtoll(str, endptr, kBase); |
| 214 #endif |
| 215 } |
| 216 static inline bool valid_func(const string_type& str) { |
| 217 return !str.empty() && !isspace(str[0]); |
| 218 } |
| 219 }; |
| 220 |
| 221 class String16ToInt64Traits { |
| 222 public: |
| 223 typedef string16 string_type; |
| 224 typedef int64 value_type; |
| 225 static const int kBase = 10; |
| 226 static inline value_type convert_func(const string_type::value_type* str, |
| 227 string_type::value_type** endptr) { |
| 228 #ifdef OS_WIN |
| 229 return _wcstoi64(str, endptr, kBase); |
| 230 #else // assume OS_POSIX |
| 231 std::string ascii_string = UTF16ToUTF8(string16(str)); |
| 232 char* ascii_end = NULL; |
| 233 value_type ret = strtoll(ascii_string.c_str(), &ascii_end, kBase); |
| 234 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
| 235 *endptr = |
| 236 const_cast<string_type::value_type*>(str) + ascii_string.length(); |
| 237 } |
| 238 return ret; |
| 239 #endif |
| 240 } |
| 241 static inline bool valid_func(const string_type& str) { |
| 242 return !str.empty() && !iswspace(str[0]); |
| 243 } |
| 244 }; |
| 245 |
| 246 // For the HexString variants, use the unsigned variants like strtoul for |
| 247 // convert_func so that input like "0x80000000" doesn't result in an overflow. |
| 248 |
| 249 class HexStringToIntTraits { |
| 250 public: |
| 251 typedef std::string string_type; |
| 252 typedef int value_type; |
| 253 static const int kBase = 16; |
| 254 static inline value_type convert_func(const string_type::value_type* str, |
| 255 string_type::value_type** endptr) { |
| 256 return strtoui(str, endptr, kBase); |
| 257 } |
| 258 static inline bool valid_func(const string_type& str) { |
| 259 return !str.empty() && !isspace(str[0]); |
| 260 } |
| 261 }; |
| 262 |
| 263 class StringToDoubleTraits { |
| 264 public: |
| 265 typedef std::string string_type; |
| 266 typedef double value_type; |
| 267 static inline value_type convert_func(const string_type::value_type* str, |
| 268 string_type::value_type** endptr) { |
| 269 return dmg_fp::strtod(str, endptr); |
| 270 } |
| 271 static inline bool valid_func(const string_type& str) { |
| 272 return !str.empty() && !isspace(str[0]); |
| 273 } |
| 274 }; |
| 275 |
| 276 template<class CHAR> |
| 277 bool HexDigitToIntT(const CHAR digit, uint8* val) { |
| 278 if (digit >= '0' && digit <= '9') |
| 279 *val = digit - '0'; |
| 280 else if (digit >= 'a' && digit <= 'f') |
| 281 *val = 10 + digit - 'a'; |
| 282 else if (digit >= 'A' && digit <= 'F') |
| 283 *val = 10 + digit - 'A'; |
| 284 else |
| 285 return false; |
| 286 return true; |
| 287 } |
| 288 |
| 289 template<typename STR> |
| 290 bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { |
| 291 DCHECK(output->size() == 0); |
| 292 size_t count = input.size(); |
| 293 if (count == 0 || (count % 2) != 0) |
| 294 return false; |
| 295 for (uintptr_t i = 0; i < count / 2; ++i) { |
| 296 uint8 msb = 0; // most significant 4 bits |
| 297 uint8 lsb = 0; // least significant 4 bits |
| 298 if (!HexDigitToIntT(input[i * 2], &msb) || |
| 299 !HexDigitToIntT(input[i * 2 + 1], &lsb)) |
| 300 return false; |
| 301 output->push_back((msb << 4) | lsb); |
| 302 } |
| 303 return true; |
| 304 } |
| 305 |
| 306 } // namespace |
| 307 |
| 308 std::string IntToString(int value) { |
| 309 return IntToStringT<std::string, int, unsigned int, true>:: |
| 310 IntToString(value); |
| 311 } |
| 312 |
| 313 string16 IntToString16(int value) { |
| 314 return IntToStringT<string16, int, unsigned int, true>:: |
| 315 IntToString(value); |
| 316 } |
| 317 |
| 318 std::string UintToString(unsigned int value) { |
| 319 return IntToStringT<std::string, unsigned int, unsigned int, false>:: |
| 320 IntToString(value); |
| 321 } |
| 322 |
| 323 string16 UintToString16(unsigned int value) { |
| 324 return IntToStringT<string16, unsigned int, unsigned int, false>:: |
| 325 IntToString(value); |
| 326 } |
| 327 |
| 328 std::string Int64ToString(int64 value) { |
| 329 return IntToStringT<std::string, int64, uint64, true>:: |
| 330 IntToString(value); |
| 331 } |
| 332 |
| 333 string16 Int64ToString16(int64 value) { |
| 334 return IntToStringT<string16, int64, uint64, true>::IntToString(value); |
| 335 } |
| 336 |
| 337 std::string Uint64ToString(uint64 value) { |
| 338 return IntToStringT<std::string, uint64, uint64, false>:: |
| 339 IntToString(value); |
| 340 } |
| 341 |
| 342 string16 Uint64ToString16(uint64 value) { |
| 343 return IntToStringT<string16, uint64, uint64, false>:: |
| 344 IntToString(value); |
| 345 } |
| 346 |
| 347 std::string DoubleToString(double value) { |
| 348 // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. |
| 349 char buffer[32]; |
| 350 dmg_fp::g_fmt(buffer, value); |
| 351 return std::string(buffer); |
| 352 } |
| 353 |
| 354 bool StringToInt(const std::string& input, int* output) { |
| 355 return StringToNumber<StringToIntTraits>(input, output); |
| 356 } |
| 357 |
| 358 bool StringToInt(const string16& input, int* output) { |
| 359 return StringToNumber<String16ToIntTraits>(input, output); |
| 360 } |
| 361 |
| 362 bool StringToInt64(const std::string& input, int64* output) { |
| 363 return StringToNumber<StringToInt64Traits>(input, output); |
| 364 } |
| 365 |
| 366 bool StringToInt64(const string16& input, int64* output) { |
| 367 return StringToNumber<String16ToInt64Traits>(input, output); |
| 368 } |
| 369 |
| 370 bool StringToDouble(const std::string& input, double* output) { |
| 371 return StringToNumber<StringToDoubleTraits>(input, output); |
| 372 } |
| 373 |
| 374 // Note: if you need to add String16ToDouble, first ask yourself if it's |
| 375 // really necessary. If it is, probably the best implementation here is to |
| 376 // convert to 8-bit and then use the 8-bit version. |
| 377 |
| 378 std::string HexEncode(const void* bytes, size_t size) { |
| 379 static const char kHexChars[] = "0123456789ABCDEF"; |
| 380 |
| 381 // Each input byte creates two output hex characters. |
| 382 std::string ret(size * 2, '\0'); |
| 383 |
| 384 for (size_t i = 0; i < size; ++i) { |
| 385 char b = reinterpret_cast<const char*>(bytes)[i]; |
| 386 ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; |
| 387 ret[(i * 2) + 1] = kHexChars[b & 0xf]; |
| 388 } |
| 389 return ret; |
| 390 } |
| 391 |
| 392 bool HexStringToInt(const std::string& input, int* output) { |
| 393 return StringToNumber<HexStringToIntTraits>(input, output); |
| 394 } |
| 395 |
| 396 bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) { |
| 397 return HexStringToBytesT(input, output); |
| 398 } |
| 399 |
| 400 } // namespace base |
OLD | NEW |