|  | // Copyright 2014 The Bazel Authors. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  | #include "src/main/cpp/util/numbers.h" | 
|  |  | 
|  | #include <errno.h>  // errno, ERANGE | 
|  | #include <limits.h> | 
|  | #include <cassert> | 
|  | #include <cinttypes> | 
|  | #include <cstdlib> | 
|  | #include <limits> | 
|  |  | 
|  | #include "src/main/cpp/util/strings.h" | 
|  |  | 
|  | namespace blaze_util { | 
|  |  | 
|  | using std::string; | 
|  |  | 
|  | static const int32_t kint32min = static_cast<int32_t>(~0x7FFFFFFF); | 
|  | static const int32_t kint32max = static_cast<int32_t>(0x7FFFFFFF); | 
|  |  | 
|  | // Represents integer values of digits. | 
|  | // Uses 36 to indicate an invalid character since we support | 
|  | // bases up to 36. | 
|  | static const int8_t kAsciiToInt[256] = { | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  // 16 36s. | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | 
|  | 36, 36, 36, 36, 36, 36, 36, | 
|  | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | 
|  | 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, | 
|  | 36, 36, 36, 36, 36, 36, | 
|  | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | 
|  | 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, | 
|  | 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, | 
|  | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36 }; | 
|  |  | 
|  | // Parse the sign. | 
|  | inline bool safe_parse_sign(const char** rest, /*inout*/ | 
|  | bool* negative_ptr  /*output*/) { | 
|  | const char* start = *rest; | 
|  | const char* end = start + strlen(start); | 
|  |  | 
|  | // Consume whitespace. | 
|  | while (start < end && ascii_isspace(start[0])) { | 
|  | ++start; | 
|  | } | 
|  | while (start < end && ascii_isspace(end[-1])) { | 
|  | --end; | 
|  | } | 
|  | if (start >= end) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Consume sign. | 
|  | *negative_ptr = (start[0] == '-'); | 
|  | if (*negative_ptr || start[0] == '+') { | 
|  | ++start; | 
|  | if (start >= end) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | *rest = start; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Consume digits. | 
|  | // | 
|  | // The classic loop: | 
|  | // | 
|  | //   for each digit | 
|  | //     value = value * base + digit | 
|  | //   value *= sign | 
|  | // | 
|  | // The classic loop needs overflow checking.  It also fails on the most | 
|  | // negative integer, -2147483648 in 32-bit two's complement representation. | 
|  | // | 
|  | // My improved loop: | 
|  | // | 
|  | //  if (!negative) | 
|  | //    for each digit | 
|  | //      value = value * base | 
|  | //      value = value + digit | 
|  | //  else | 
|  | //    for each digit | 
|  | //      value = value * base | 
|  | //      value = value - digit | 
|  | // | 
|  | // Overflow checking becomes simple. | 
|  |  | 
|  | inline bool safe_parse_positive_int(const char *text, int* value_p) { | 
|  | int value = 0; | 
|  | const int vmax = std::numeric_limits<int>::max(); | 
|  | static_assert(vmax > 0, ""); | 
|  | const int vmax_over_base = vmax / 10; | 
|  | const char* start = text; | 
|  | const char* end = start + strlen(text); | 
|  | // loop over digits | 
|  | for (; start < end; ++start) { | 
|  | unsigned char c = static_cast<unsigned char>(start[0]); | 
|  | int digit = kAsciiToInt[c]; | 
|  | if (digit >= 10) { | 
|  | *value_p = value; | 
|  | return false; | 
|  | } | 
|  | if (value > vmax_over_base) { | 
|  | *value_p = vmax; | 
|  | return false; | 
|  | } | 
|  | value *= 10; | 
|  | if (value > vmax - digit) { | 
|  | *value_p = vmax; | 
|  | return false; | 
|  | } | 
|  | value += digit; | 
|  | } | 
|  | *value_p = value; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | inline bool safe_parse_negative_int(const char *text, int* value_p) { | 
|  | int value = 0; | 
|  | const int vmin = std::numeric_limits<int>::min(); | 
|  | static_assert(vmin < 0, ""); | 
|  | int vmin_over_base = vmin / 10; | 
|  | // 2003 c++ standard [expr.mul] | 
|  | // "... the sign of the remainder is implementation-defined." | 
|  | // Although (vmin/base)*base + vmin%base is always vmin. | 
|  | // 2011 c++ standard tightens the spec but we cannot rely on it. | 
|  | if (vmin % 10 > 0) { | 
|  | vmin_over_base += 1; | 
|  | } | 
|  | const char* start = text; | 
|  | const char* end = start + strlen(text); | 
|  | // loop over digits | 
|  | for (; start < end; ++start) { | 
|  | unsigned char c = static_cast<unsigned char>(start[0]); | 
|  | int digit = kAsciiToInt[c]; | 
|  | if (digit >= 10) { | 
|  | *value_p = value; | 
|  | return false; | 
|  | } | 
|  | if (value < vmin_over_base) { | 
|  | *value_p = vmin; | 
|  | return false; | 
|  | } | 
|  | value *= 10; | 
|  | if (value < vmin + digit) { | 
|  | *value_p = vmin; | 
|  | return false; | 
|  | } | 
|  | value -= digit; | 
|  | } | 
|  | *value_p = value; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool safe_strto32(const string &text, int *value_p) { | 
|  | *value_p = 0; | 
|  | const char* rest = text.c_str(); | 
|  | bool negative; | 
|  | if (!safe_parse_sign(&rest, &negative)) { | 
|  | return false; | 
|  | } | 
|  | if (!negative) { | 
|  | return safe_parse_positive_int(rest, value_p); | 
|  | } else { | 
|  | return safe_parse_negative_int(rest, value_p); | 
|  | } | 
|  | } | 
|  |  | 
|  | int32_t strto32(const char *str, char **endptr, int base) { | 
|  | if (sizeof(int32_t) == sizeof(long)) {  // NOLINT | 
|  | return static_cast<int32_t>(strtol(str, endptr, base));  // NOLINT | 
|  | } | 
|  | const int saved_errno = errno; | 
|  | errno = 0; | 
|  | const long result = strtol(str, endptr, base);  // NOLINT | 
|  | if (errno == ERANGE && result == LONG_MIN) { | 
|  | return kint32min; | 
|  | } else if (errno == ERANGE && result == LONG_MAX) { | 
|  | return kint32max; | 
|  | } else if (errno == 0 && result < kint32min) { | 
|  | errno = ERANGE; | 
|  | return kint32min; | 
|  | } else if (errno == 0 && result > kint32max) { | 
|  | errno = ERANGE; | 
|  | return kint32max; | 
|  | } | 
|  | if (errno == 0) | 
|  | errno = saved_errno; | 
|  | return static_cast<int32_t>(result); | 
|  | } | 
|  |  | 
|  | }  // namespace blaze_util |