security/sandbox/chromium/base/strings/string_number_conversions.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/sandbox/chromium/base/strings/string_number_conversions.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,516 @@
     1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#include "base/strings/string_number_conversions.h"
     1.9 +
    1.10 +#include <ctype.h>
    1.11 +#include <errno.h>
    1.12 +#include <stdlib.h>
    1.13 +#include <wctype.h>
    1.14 +
    1.15 +#include <limits>
    1.16 +
    1.17 +#include "base/logging.h"
    1.18 +#include "base/scoped_clear_errno.h"
    1.19 +#include "base/strings/utf_string_conversions.h"
    1.20 +#include "base/third_party/dmg_fp/dmg_fp.h"
    1.21 +
    1.22 +namespace base {
    1.23 +
    1.24 +namespace {
    1.25 +
    1.26 +template <typename STR, typename INT, typename UINT, bool NEG>
    1.27 +struct IntToStringT {
    1.28 +  // This is to avoid a compiler warning about unary minus on unsigned type.
    1.29 +  // For example, say you had the following code:
    1.30 +  //   template <typename INT>
    1.31 +  //   INT abs(INT value) { return value < 0 ? -value : value; }
    1.32 +  // Even though if INT is unsigned, it's impossible for value < 0, so the
    1.33 +  // unary minus will never be taken, the compiler will still generate a
    1.34 +  // warning.  We do a little specialization dance...
    1.35 +  template <typename INT2, typename UINT2, bool NEG2>
    1.36 +  struct ToUnsignedT {};
    1.37 +
    1.38 +  template <typename INT2, typename UINT2>
    1.39 +  struct ToUnsignedT<INT2, UINT2, false> {
    1.40 +    static UINT2 ToUnsigned(INT2 value) {
    1.41 +      return static_cast<UINT2>(value);
    1.42 +    }
    1.43 +  };
    1.44 +
    1.45 +  template <typename INT2, typename UINT2>
    1.46 +  struct ToUnsignedT<INT2, UINT2, true> {
    1.47 +    static UINT2 ToUnsigned(INT2 value) {
    1.48 +      return static_cast<UINT2>(value < 0 ? -value : value);
    1.49 +    }
    1.50 +  };
    1.51 +
    1.52 +  // This set of templates is very similar to the above templates, but
    1.53 +  // for testing whether an integer is negative.
    1.54 +  template <typename INT2, bool NEG2>
    1.55 +  struct TestNegT {};
    1.56 +  template <typename INT2>
    1.57 +  struct TestNegT<INT2, false> {
    1.58 +    static bool TestNeg(INT2 value) {
    1.59 +      // value is unsigned, and can never be negative.
    1.60 +      return false;
    1.61 +    }
    1.62 +  };
    1.63 +  template <typename INT2>
    1.64 +  struct TestNegT<INT2, true> {
    1.65 +    static bool TestNeg(INT2 value) {
    1.66 +      return value < 0;
    1.67 +    }
    1.68 +  };
    1.69 +
    1.70 +  static STR IntToString(INT value) {
    1.71 +    // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4.
    1.72 +    // So round up to allocate 3 output characters per byte, plus 1 for '-'.
    1.73 +    const int kOutputBufSize = 3 * sizeof(INT) + 1;
    1.74 +
    1.75 +    // Allocate the whole string right away, we will right back to front, and
    1.76 +    // then return the substr of what we ended up using.
    1.77 +    STR outbuf(kOutputBufSize, 0);
    1.78 +
    1.79 +    bool is_neg = TestNegT<INT, NEG>::TestNeg(value);
    1.80 +    // Even though is_neg will never be true when INT is parameterized as
    1.81 +    // unsigned, even the presence of the unary operation causes a warning.
    1.82 +    UINT res = ToUnsignedT<INT, UINT, NEG>::ToUnsigned(value);
    1.83 +
    1.84 +    for (typename STR::iterator it = outbuf.end();;) {
    1.85 +      --it;
    1.86 +      DCHECK(it != outbuf.begin());
    1.87 +      *it = static_cast<typename STR::value_type>((res % 10) + '0');
    1.88 +      res /= 10;
    1.89 +
    1.90 +      // We're done..
    1.91 +      if (res == 0) {
    1.92 +        if (is_neg) {
    1.93 +          --it;
    1.94 +          DCHECK(it != outbuf.begin());
    1.95 +          *it = static_cast<typename STR::value_type>('-');
    1.96 +        }
    1.97 +        return STR(it, outbuf.end());
    1.98 +      }
    1.99 +    }
   1.100 +    NOTREACHED();
   1.101 +    return STR();
   1.102 +  }
   1.103 +};
   1.104 +
   1.105 +// Utility to convert a character to a digit in a given base
   1.106 +template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit {
   1.107 +};
   1.108 +
   1.109 +// Faster specialization for bases <= 10
   1.110 +template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
   1.111 + public:
   1.112 +  static bool Convert(CHAR c, uint8* digit) {
   1.113 +    if (c >= '0' && c < '0' + BASE) {
   1.114 +      *digit = c - '0';
   1.115 +      return true;
   1.116 +    }
   1.117 +    return false;
   1.118 +  }
   1.119 +};
   1.120 +
   1.121 +// Specialization for bases where 10 < base <= 36
   1.122 +template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
   1.123 + public:
   1.124 +  static bool Convert(CHAR c, uint8* digit) {
   1.125 +    if (c >= '0' && c <= '9') {
   1.126 +      *digit = c - '0';
   1.127 +    } else if (c >= 'a' && c < 'a' + BASE - 10) {
   1.128 +      *digit = c - 'a' + 10;
   1.129 +    } else if (c >= 'A' && c < 'A' + BASE - 10) {
   1.130 +      *digit = c - 'A' + 10;
   1.131 +    } else {
   1.132 +      return false;
   1.133 +    }
   1.134 +    return true;
   1.135 +  }
   1.136 +};
   1.137 +
   1.138 +template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) {
   1.139 +  return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit);
   1.140 +}
   1.141 +
   1.142 +// There is an IsWhitespace for wchars defined in string_util.h, but it is
   1.143 +// locale independent, whereas the functions we are replacing were
   1.144 +// locale-dependent. TBD what is desired, but for the moment let's not introduce
   1.145 +// a change in behaviour.
   1.146 +template<typename CHAR> class WhitespaceHelper {
   1.147 +};
   1.148 +
   1.149 +template<> class WhitespaceHelper<char> {
   1.150 + public:
   1.151 +  static bool Invoke(char c) {
   1.152 +    return 0 != isspace(static_cast<unsigned char>(c));
   1.153 +  }
   1.154 +};
   1.155 +
   1.156 +template<> class WhitespaceHelper<char16> {
   1.157 + public:
   1.158 +  static bool Invoke(char16 c) {
   1.159 +    return 0 != iswspace(c);
   1.160 +  }
   1.161 +};
   1.162 +
   1.163 +template<typename CHAR> bool LocalIsWhitespace(CHAR c) {
   1.164 +  return WhitespaceHelper<CHAR>::Invoke(c);
   1.165 +}
   1.166 +
   1.167 +// IteratorRangeToNumberTraits should provide:
   1.168 +//  - a typedef for iterator_type, the iterator type used as input.
   1.169 +//  - a typedef for value_type, the target numeric type.
   1.170 +//  - static functions min, max (returning the minimum and maximum permitted
   1.171 +//    values)
   1.172 +//  - constant kBase, the base in which to interpret the input
   1.173 +template<typename IteratorRangeToNumberTraits>
   1.174 +class IteratorRangeToNumber {
   1.175 + public:
   1.176 +  typedef IteratorRangeToNumberTraits traits;
   1.177 +  typedef typename traits::iterator_type const_iterator;
   1.178 +  typedef typename traits::value_type value_type;
   1.179 +
   1.180 +  // Generalized iterator-range-to-number conversion.
   1.181 +  //
   1.182 +  static bool Invoke(const_iterator begin,
   1.183 +                     const_iterator end,
   1.184 +                     value_type* output) {
   1.185 +    bool valid = true;
   1.186 +
   1.187 +    while (begin != end && LocalIsWhitespace(*begin)) {
   1.188 +      valid = false;
   1.189 +      ++begin;
   1.190 +    }
   1.191 +
   1.192 +    if (begin != end && *begin == '-') {
   1.193 +      if (!std::numeric_limits<value_type>::is_signed) {
   1.194 +        valid = false;
   1.195 +      } else if (!Negative::Invoke(begin + 1, end, output)) {
   1.196 +        valid = false;
   1.197 +      }
   1.198 +    } else {
   1.199 +      if (begin != end && *begin == '+') {
   1.200 +        ++begin;
   1.201 +      }
   1.202 +      if (!Positive::Invoke(begin, end, output)) {
   1.203 +        valid = false;
   1.204 +      }
   1.205 +    }
   1.206 +
   1.207 +    return valid;
   1.208 +  }
   1.209 +
   1.210 + private:
   1.211 +  // Sign provides:
   1.212 +  //  - a static function, CheckBounds, that determines whether the next digit
   1.213 +  //    causes an overflow/underflow
   1.214 +  //  - a static function, Increment, that appends the next digit appropriately
   1.215 +  //    according to the sign of the number being parsed.
   1.216 +  template<typename Sign>
   1.217 +  class Base {
   1.218 +   public:
   1.219 +    static bool Invoke(const_iterator begin, const_iterator end,
   1.220 +                       typename traits::value_type* output) {
   1.221 +      *output = 0;
   1.222 +
   1.223 +      if (begin == end) {
   1.224 +        return false;
   1.225 +      }
   1.226 +
   1.227 +      // Note: no performance difference was found when using template
   1.228 +      // specialization to remove this check in bases other than 16
   1.229 +      if (traits::kBase == 16 && end - begin > 2 && *begin == '0' &&
   1.230 +          (*(begin + 1) == 'x' || *(begin + 1) == 'X')) {
   1.231 +        begin += 2;
   1.232 +      }
   1.233 +
   1.234 +      for (const_iterator current = begin; current != end; ++current) {
   1.235 +        uint8 new_digit = 0;
   1.236 +
   1.237 +        if (!CharToDigit<traits::kBase>(*current, &new_digit)) {
   1.238 +          return false;
   1.239 +        }
   1.240 +
   1.241 +        if (current != begin) {
   1.242 +          if (!Sign::CheckBounds(output, new_digit)) {
   1.243 +            return false;
   1.244 +          }
   1.245 +          *output *= traits::kBase;
   1.246 +        }
   1.247 +
   1.248 +        Sign::Increment(new_digit, output);
   1.249 +      }
   1.250 +      return true;
   1.251 +    }
   1.252 +  };
   1.253 +
   1.254 +  class Positive : public Base<Positive> {
   1.255 +   public:
   1.256 +    static bool CheckBounds(value_type* output, uint8 new_digit) {
   1.257 +      if (*output > static_cast<value_type>(traits::max() / traits::kBase) ||
   1.258 +          (*output == static_cast<value_type>(traits::max() / traits::kBase) &&
   1.259 +           new_digit > traits::max() % traits::kBase)) {
   1.260 +        *output = traits::max();
   1.261 +        return false;
   1.262 +      }
   1.263 +      return true;
   1.264 +    }
   1.265 +    static void Increment(uint8 increment, value_type* output) {
   1.266 +      *output += increment;
   1.267 +    }
   1.268 +  };
   1.269 +
   1.270 +  class Negative : public Base<Negative> {
   1.271 +   public:
   1.272 +    static bool CheckBounds(value_type* output, uint8 new_digit) {
   1.273 +      if (*output < traits::min() / traits::kBase ||
   1.274 +          (*output == traits::min() / traits::kBase &&
   1.275 +           new_digit > 0 - traits::min() % traits::kBase)) {
   1.276 +        *output = traits::min();
   1.277 +        return false;
   1.278 +      }
   1.279 +      return true;
   1.280 +    }
   1.281 +    static void Increment(uint8 increment, value_type* output) {
   1.282 +      *output -= increment;
   1.283 +    }
   1.284 +  };
   1.285 +};
   1.286 +
   1.287 +template<typename ITERATOR, typename VALUE, int BASE>
   1.288 +class BaseIteratorRangeToNumberTraits {
   1.289 + public:
   1.290 +  typedef ITERATOR iterator_type;
   1.291 +  typedef VALUE value_type;
   1.292 +  static value_type min() {
   1.293 +    return std::numeric_limits<value_type>::min();
   1.294 +  }
   1.295 +  static value_type max() {
   1.296 +    return std::numeric_limits<value_type>::max();
   1.297 +  }
   1.298 +  static const int kBase = BASE;
   1.299 +};
   1.300 +
   1.301 +template<typename ITERATOR>
   1.302 +class BaseHexIteratorRangeToIntTraits
   1.303 +    : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> {
   1.304 +};
   1.305 +
   1.306 +template<typename ITERATOR>
   1.307 +class BaseHexIteratorRangeToInt64Traits
   1.308 +    : public BaseIteratorRangeToNumberTraits<ITERATOR, int64, 16> {
   1.309 +};
   1.310 +
   1.311 +template<typename ITERATOR>
   1.312 +class BaseHexIteratorRangeToUInt64Traits
   1.313 +    : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64, 16> {
   1.314 +};
   1.315 +
   1.316 +typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator>
   1.317 +    HexIteratorRangeToIntTraits;
   1.318 +
   1.319 +typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator>
   1.320 +    HexIteratorRangeToInt64Traits;
   1.321 +
   1.322 +typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator>
   1.323 +    HexIteratorRangeToUInt64Traits;
   1.324 +
   1.325 +template<typename STR>
   1.326 +bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) {
   1.327 +  DCHECK_EQ(output->size(), 0u);
   1.328 +  size_t count = input.size();
   1.329 +  if (count == 0 || (count % 2) != 0)
   1.330 +    return false;
   1.331 +  for (uintptr_t i = 0; i < count / 2; ++i) {
   1.332 +    uint8 msb = 0;  // most significant 4 bits
   1.333 +    uint8 lsb = 0;  // least significant 4 bits
   1.334 +    if (!CharToDigit<16>(input[i * 2], &msb) ||
   1.335 +        !CharToDigit<16>(input[i * 2 + 1], &lsb))
   1.336 +      return false;
   1.337 +    output->push_back((msb << 4) | lsb);
   1.338 +  }
   1.339 +  return true;
   1.340 +}
   1.341 +
   1.342 +template <typename VALUE, int BASE>
   1.343 +class StringPieceToNumberTraits
   1.344 +    : public BaseIteratorRangeToNumberTraits<StringPiece::const_iterator,
   1.345 +                                             VALUE,
   1.346 +                                             BASE> {
   1.347 +};
   1.348 +
   1.349 +template <typename VALUE>
   1.350 +bool StringToIntImpl(const StringPiece& input, VALUE* output) {
   1.351 +  return IteratorRangeToNumber<StringPieceToNumberTraits<VALUE, 10> >::Invoke(
   1.352 +      input.begin(), input.end(), output);
   1.353 +}
   1.354 +
   1.355 +template <typename VALUE, int BASE>
   1.356 +class StringPiece16ToNumberTraits
   1.357 +    : public BaseIteratorRangeToNumberTraits<StringPiece16::const_iterator,
   1.358 +                                             VALUE,
   1.359 +                                             BASE> {
   1.360 +};
   1.361 +
   1.362 +template <typename VALUE>
   1.363 +bool String16ToIntImpl(const StringPiece16& input, VALUE* output) {
   1.364 +  return IteratorRangeToNumber<StringPiece16ToNumberTraits<VALUE, 10> >::Invoke(
   1.365 +      input.begin(), input.end(), output);
   1.366 +}
   1.367 +
   1.368 +}  // namespace
   1.369 +
   1.370 +std::string IntToString(int value) {
   1.371 +  return IntToStringT<std::string, int, unsigned int, true>::
   1.372 +      IntToString(value);
   1.373 +}
   1.374 +
   1.375 +string16 IntToString16(int value) {
   1.376 +  return IntToStringT<string16, int, unsigned int, true>::
   1.377 +      IntToString(value);
   1.378 +}
   1.379 +
   1.380 +std::string UintToString(unsigned int value) {
   1.381 +  return IntToStringT<std::string, unsigned int, unsigned int, false>::
   1.382 +      IntToString(value);
   1.383 +}
   1.384 +
   1.385 +string16 UintToString16(unsigned int value) {
   1.386 +  return IntToStringT<string16, unsigned int, unsigned int, false>::
   1.387 +      IntToString(value);
   1.388 +}
   1.389 +
   1.390 +std::string Int64ToString(int64 value) {
   1.391 +  return IntToStringT<std::string, int64, uint64, true>::
   1.392 +      IntToString(value);
   1.393 +}
   1.394 +
   1.395 +string16 Int64ToString16(int64 value) {
   1.396 +  return IntToStringT<string16, int64, uint64, true>::IntToString(value);
   1.397 +}
   1.398 +
   1.399 +std::string Uint64ToString(uint64 value) {
   1.400 +  return IntToStringT<std::string, uint64, uint64, false>::
   1.401 +      IntToString(value);
   1.402 +}
   1.403 +
   1.404 +string16 Uint64ToString16(uint64 value) {
   1.405 +  return IntToStringT<string16, uint64, uint64, false>::
   1.406 +      IntToString(value);
   1.407 +}
   1.408 +
   1.409 +std::string DoubleToString(double value) {
   1.410 +  // According to g_fmt.cc, it is sufficient to declare a buffer of size 32.
   1.411 +  char buffer[32];
   1.412 +  dmg_fp::g_fmt(buffer, value);
   1.413 +  return std::string(buffer);
   1.414 +}
   1.415 +
   1.416 +bool StringToInt(const StringPiece& input, int* output) {
   1.417 +  return StringToIntImpl(input, output);
   1.418 +}
   1.419 +
   1.420 +bool StringToInt(const StringPiece16& input, int* output) {
   1.421 +  return String16ToIntImpl(input, output);
   1.422 +}
   1.423 +
   1.424 +bool StringToUint(const StringPiece& input, unsigned* output) {
   1.425 +  return StringToIntImpl(input, output);
   1.426 +}
   1.427 +
   1.428 +bool StringToUint(const StringPiece16& input, unsigned* output) {
   1.429 +  return String16ToIntImpl(input, output);
   1.430 +}
   1.431 +
   1.432 +bool StringToInt64(const StringPiece& input, int64* output) {
   1.433 +  return StringToIntImpl(input, output);
   1.434 +}
   1.435 +
   1.436 +bool StringToInt64(const StringPiece16& input, int64* output) {
   1.437 +  return String16ToIntImpl(input, output);
   1.438 +}
   1.439 +
   1.440 +bool StringToUint64(const StringPiece& input, uint64* output) {
   1.441 +  return StringToIntImpl(input, output);
   1.442 +}
   1.443 +
   1.444 +bool StringToUint64(const StringPiece16& input, uint64* output) {
   1.445 +  return String16ToIntImpl(input, output);
   1.446 +}
   1.447 +
   1.448 +bool StringToSizeT(const StringPiece& input, size_t* output) {
   1.449 +  return StringToIntImpl(input, output);
   1.450 +}
   1.451 +
   1.452 +bool StringToSizeT(const StringPiece16& input, size_t* output) {
   1.453 +  return String16ToIntImpl(input, output);
   1.454 +}
   1.455 +
   1.456 +bool StringToDouble(const std::string& input, double* output) {
   1.457 +  // Thread-safe?  It is on at least Mac, Linux, and Windows.
   1.458 +  ScopedClearErrno clear_errno;
   1.459 +
   1.460 +  char* endptr = NULL;
   1.461 +  *output = dmg_fp::strtod(input.c_str(), &endptr);
   1.462 +
   1.463 +  // Cases to return false:
   1.464 +  //  - If errno is ERANGE, there was an overflow or underflow.
   1.465 +  //  - If the input string is empty, there was nothing to parse.
   1.466 +  //  - If endptr does not point to the end of the string, there are either
   1.467 +  //    characters remaining in the string after a parsed number, or the string
   1.468 +  //    does not begin with a parseable number.  endptr is compared to the
   1.469 +  //    expected end given the string's stated length to correctly catch cases
   1.470 +  //    where the string contains embedded NUL characters.
   1.471 +  //  - If the first character is a space, there was leading whitespace
   1.472 +  return errno == 0 &&
   1.473 +         !input.empty() &&
   1.474 +         input.c_str() + input.length() == endptr &&
   1.475 +         !isspace(input[0]);
   1.476 +}
   1.477 +
   1.478 +// Note: if you need to add String16ToDouble, first ask yourself if it's
   1.479 +// really necessary. If it is, probably the best implementation here is to
   1.480 +// convert to 8-bit and then use the 8-bit version.
   1.481 +
   1.482 +// Note: if you need to add an iterator range version of StringToDouble, first
   1.483 +// ask yourself if it's really necessary. If it is, probably the best
   1.484 +// implementation here is to instantiate a string and use the string version.
   1.485 +
   1.486 +std::string HexEncode(const void* bytes, size_t size) {
   1.487 +  static const char kHexChars[] = "0123456789ABCDEF";
   1.488 +
   1.489 +  // Each input byte creates two output hex characters.
   1.490 +  std::string ret(size * 2, '\0');
   1.491 +
   1.492 +  for (size_t i = 0; i < size; ++i) {
   1.493 +    char b = reinterpret_cast<const char*>(bytes)[i];
   1.494 +    ret[(i * 2)] = kHexChars[(b >> 4) & 0xf];
   1.495 +    ret[(i * 2) + 1] = kHexChars[b & 0xf];
   1.496 +  }
   1.497 +  return ret;
   1.498 +}
   1.499 +
   1.500 +bool HexStringToInt(const StringPiece& input, int* output) {
   1.501 +  return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke(
   1.502 +    input.begin(), input.end(), output);
   1.503 +}
   1.504 +
   1.505 +bool HexStringToInt64(const StringPiece& input, int64* output) {
   1.506 +  return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke(
   1.507 +    input.begin(), input.end(), output);
   1.508 +}
   1.509 +
   1.510 +bool HexStringToUInt64(const StringPiece& input, uint64* output) {
   1.511 +  return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke(
   1.512 +      input.begin(), input.end(), output);
   1.513 +}
   1.514 +
   1.515 +bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) {
   1.516 +  return HexStringToBytesT(input, output);
   1.517 +}
   1.518 +
   1.519 +}  // namespace base

mercurial