| // 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 |