1 /* 2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_STRING_TO_NUMBER_H_ 12 #define RTC_BASE_STRING_TO_NUMBER_H_ 13 14 #include <limits> 15 #include <string> 16 #include <type_traits> 17 18 #include "absl/types/optional.h" 19 20 namespace rtc { 21 22 // This file declares a family of functions to parse integers from strings. 23 // The standard C library functions either fail to indicate errors (atoi, etc.) 24 // or are a hassle to work with (strtol, sscanf, etc.). The standard C++ library 25 // functions (std::stoi, etc.) indicate errors by throwing exceptions, which 26 // are disabled in WebRTC. 27 // 28 // Integers are parsed using one of the following functions: 29 // absl::optional<int-type> StringToNumber(const char* str, int base = 10); 30 // absl::optional<int-type> StringToNumber(const std::string& str, 31 // int base = 10); 32 // 33 // These functions parse a value from the beginning of a string into one of the 34 // fundamental integer types, or returns an empty Optional if parsing 35 // failed. Values outside of the range supported by the type will be 36 // rejected. The strings must begin with a digit or a minus sign. No leading 37 // space nor trailing contents are allowed. 38 // By setting base to 0, one of octal, decimal or hexadecimal will be 39 // detected from the string's prefix (0, nothing or 0x, respectively). 40 // If non-zero, base can be set to a value between 2 and 36 inclusively. 41 // 42 // If desired, this interface could be extended with support for floating-point 43 // types. 44 45 namespace string_to_number_internal { 46 // These must be (unsigned) long long, to match the signature of strto(u)ll. 47 using unsigned_type = unsigned long long; // NOLINT(runtime/int) 48 using signed_type = long long; // NOLINT(runtime/int) 49 50 absl::optional<signed_type> ParseSigned(const char* str, int base); 51 absl::optional<unsigned_type> ParseUnsigned(const char* str, int base); 52 53 template <typename T> 54 absl::optional<T> ParseFloatingPoint(const char* str); 55 } // namespace string_to_number_internal 56 57 template <typename T> 58 typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, 59 absl::optional<T>>::type 60 StringToNumber(const char* str, int base = 10) { 61 using string_to_number_internal::signed_type; 62 static_assert( 63 std::numeric_limits<T>::max() <= 64 std::numeric_limits<signed_type>::max() && 65 std::numeric_limits<T>::lowest() >= 66 std::numeric_limits<signed_type>::lowest(), 67 "StringToNumber only supports signed integers as large as long long int"); 68 absl::optional<signed_type> value = 69 string_to_number_internal::ParseSigned(str, base); 70 if (value && *value >= std::numeric_limits<T>::lowest() && 71 *value <= std::numeric_limits<T>::max()) { 72 return static_cast<T>(*value); 73 } 74 return absl::nullopt; 75 } 76 77 template <typename T> 78 typename std::enable_if<std::is_integral<T>::value && 79 std::is_unsigned<T>::value, 80 absl::optional<T>>::type 81 StringToNumber(const char* str, int base = 10) { 82 using string_to_number_internal::unsigned_type; 83 static_assert(std::numeric_limits<T>::max() <= 84 std::numeric_limits<unsigned_type>::max(), 85 "StringToNumber only supports unsigned integers as large as " 86 "unsigned long long int"); 87 absl::optional<unsigned_type> value = 88 string_to_number_internal::ParseUnsigned(str, base); 89 if (value && *value <= std::numeric_limits<T>::max()) { 90 return static_cast<T>(*value); 91 } 92 return absl::nullopt; 93 } 94 95 template <typename T> 96 typename std::enable_if<std::is_floating_point<T>::value, 97 absl::optional<T>>::type 98 StringToNumber(const char* str, int base = 10) { 99 static_assert( 100 std::numeric_limits<T>::max() <= std::numeric_limits<long double>::max(), 101 "StringToNumber only supports floating-point numbers as large " 102 "as long double"); 103 return string_to_number_internal::ParseFloatingPoint<T>(str); 104 } 105 106 // The std::string overloads only exists if there is a matching const char* 107 // version. 108 template <typename T> 109 auto StringToNumber(const std::string& str, int base = 10) 110 -> decltype(StringToNumber<T>(str.c_str(), base)) { 111 return StringToNumber<T>(str.c_str(), base); 112 } 113 114 } // namespace rtc 115 116 #endif // RTC_BASE_STRING_TO_NUMBER_H_ 117