| /* | 
 |  *  Copyright 2017 The WebRTC Project Authors. All rights reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "rtc_base/string_to_number.h" | 
 |  | 
 | #include <cctype> | 
 | #include <cerrno> | 
 | #include <cstdlib> | 
 | #include <optional> | 
 | #include <string> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 |  | 
 | namespace webrtc { | 
 | namespace string_to_number_internal { | 
 |  | 
 | std::optional<signed_type> ParseSigned(absl::string_view str, int base) { | 
 |   if (str.empty()) | 
 |     return std::nullopt; | 
 |  | 
 |   if (isdigit(static_cast<unsigned char>(str[0])) || str[0] == '-') { | 
 |     std::string str_str(str); | 
 |     char* end = nullptr; | 
 |     errno = 0; | 
 |     const signed_type value = std::strtoll(str_str.c_str(), &end, base); | 
 |     // Check for errors and also make sure that there were no embedded nuls in | 
 |     // the input string. | 
 |     if (end == str_str.c_str() + str_str.size() && errno == 0) { | 
 |       return value; | 
 |     } | 
 |   } | 
 |   return std::nullopt; | 
 | } | 
 |  | 
 | std::optional<unsigned_type> ParseUnsigned(absl::string_view str, int base) { | 
 |   if (str.empty()) | 
 |     return std::nullopt; | 
 |  | 
 |   if (isdigit(static_cast<unsigned char>(str[0])) || str[0] == '-') { | 
 |     std::string str_str(str); | 
 |     // Explicitly discard negative values. std::strtoull parsing causes unsigned | 
 |     // wraparound. We cannot just reject values that start with -, though, since | 
 |     // -0 is perfectly fine, as is -0000000000000000000000000000000. | 
 |     const bool is_negative = str[0] == '-'; | 
 |     char* end = nullptr; | 
 |     errno = 0; | 
 |     const unsigned_type value = std::strtoull(str_str.c_str(), &end, base); | 
 |     // Check for errors and also make sure that there were no embedded nuls in | 
 |     // the input string. | 
 |     if (end == str_str.c_str() + str_str.size() && errno == 0 && | 
 |         (value == 0 || !is_negative)) { | 
 |       return value; | 
 |     } | 
 |   } | 
 |   return std::nullopt; | 
 | } | 
 |  | 
 | template <typename T> | 
 | T StrToT(const char* str, char** str_end); | 
 |  | 
 | template <> | 
 | inline float StrToT(const char* str, char** str_end) { | 
 |   return std::strtof(str, str_end); | 
 | } | 
 |  | 
 | template <> | 
 | inline double StrToT(const char* str, char** str_end) { | 
 |   return std::strtod(str, str_end); | 
 | } | 
 |  | 
 | template <> | 
 | inline long double StrToT(const char* str, char** str_end) { | 
 |   return std::strtold(str, str_end); | 
 | } | 
 |  | 
 | template <typename T> | 
 | std::optional<T> ParseFloatingPoint(absl::string_view str) { | 
 |   if (str.empty()) | 
 |     return std::nullopt; | 
 |  | 
 |   if (str[0] == '\0') | 
 |     return std::nullopt; | 
 |   std::string str_str(str); | 
 |   char* end = nullptr; | 
 |   errno = 0; | 
 |   const T value = StrToT<T>(str_str.c_str(), &end); | 
 |   if (end == str_str.c_str() + str_str.size() && errno == 0) { | 
 |     return value; | 
 |   } | 
 |   return std::nullopt; | 
 | } | 
 |  | 
 | template std::optional<float> ParseFloatingPoint(absl::string_view str); | 
 | template std::optional<double> ParseFloatingPoint(absl::string_view str); | 
 | template std::optional<long double> ParseFloatingPoint(absl::string_view str); | 
 |  | 
 | }  // namespace string_to_number_internal | 
 | }  // namespace webrtc |