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