blob: 1b7cc5fa6c9c3b1081c02362f401befb645faa3d [file] [log] [blame]
Elliott Hughes7dd8e202015-09-04 16:26:51 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Elliott Hughesf5224432016-03-23 15:04:52 -070017#ifndef ANDROID_BASE_PARSEINT_H
18#define ANDROID_BASE_PARSEINT_H
Elliott Hughes7dd8e202015-09-04 16:26:51 -070019
20#include <errno.h>
21#include <stdlib.h>
Elliott Hughes06768992018-04-19 19:48:25 -070022#include <string.h>
Elliott Hughes7dd8e202015-09-04 16:26:51 -070023
24#include <limits>
Elliott Hughes31d04db2016-10-11 17:09:00 -070025#include <string>
Elliott Hughes7dd8e202015-09-04 16:26:51 -070026
27namespace android {
28namespace base {
29
30// Parses the unsigned decimal integer in the string 's' and sets 'out' to
31// that value. Optionally allows the caller to define a 'max' beyond which
Elliott Hughes31d04db2016-10-11 17:09:00 -070032// otherwise valid values will be rejected. Returns boolean success; 'out'
33// is untouched if parsing fails.
Elliott Hughes7dd8e202015-09-04 16:26:51 -070034template <typename T>
Elliott Hughes06768992018-04-19 19:48:25 -070035bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
36 bool allow_suffixes = false) {
Yifan Hong6b1e33b2016-10-07 16:48:17 -070037 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
Elliott Hughes7dd8e202015-09-04 16:26:51 -070038 errno = 0;
39 char* end;
Elliott Hughesefa901e2015-11-02 09:01:53 -080040 unsigned long long int result = strtoull(s, &end, base);
Elliott Hughes06768992018-04-19 19:48:25 -070041 if (errno != 0 || end == s) return false;
42 if (*end != '\0') {
43 const char* suffixes = "bkmgtpe";
44 const char* suffix;
45 if (!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) return false;
46#if __clang__ // TODO: win32 still builds with GCC :-(
47 if (__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) return false;
48#endif
Elliott Hughes7dd8e202015-09-04 16:26:51 -070049 }
50 if (max < result) {
51 return false;
52 }
53 *out = static_cast<T>(result);
54 return true;
55}
56
Elliott Hughes31d04db2016-10-11 17:09:00 -070057// TODO: string_view
58template <typename T>
Elliott Hughes06768992018-04-19 19:48:25 -070059bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
60 bool allow_suffixes = false) {
61 return ParseUint(s.c_str(), out, max, allow_suffixes);
62}
63
64template <typename T>
65bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
66 return ParseUint(s, out, max, true);
67}
68
69// TODO: string_view
70template <typename T>
71bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
72 return ParseByteCount(s.c_str(), out, max);
Elliott Hughes31d04db2016-10-11 17:09:00 -070073}
74
Elliott Hughes7dd8e202015-09-04 16:26:51 -070075// Parses the signed decimal integer in the string 's' and sets 'out' to
76// that value. Optionally allows the caller to define a 'min' and 'max
77// beyond which otherwise valid values will be rejected. Returns boolean
Elliott Hughes31d04db2016-10-11 17:09:00 -070078// success; 'out' is untouched if parsing fails.
Elliott Hughes7dd8e202015-09-04 16:26:51 -070079template <typename T>
80bool ParseInt(const char* s, T* out,
81 T min = std::numeric_limits<T>::min(),
82 T max = std::numeric_limits<T>::max()) {
Yifan Hong6b1e33b2016-10-07 16:48:17 -070083 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
Elliott Hughes7dd8e202015-09-04 16:26:51 -070084 errno = 0;
85 char* end;
Elliott Hughesefa901e2015-11-02 09:01:53 -080086 long long int result = strtoll(s, &end, base);
Elliott Hughes7dd8e202015-09-04 16:26:51 -070087 if (errno != 0 || s == end || *end != '\0') {
88 return false;
89 }
90 if (result < min || max < result) {
91 return false;
92 }
93 *out = static_cast<T>(result);
94 return true;
95}
96
Elliott Hughes31d04db2016-10-11 17:09:00 -070097// TODO: string_view
98template <typename T>
99bool ParseInt(const std::string& s, T* out,
100 T min = std::numeric_limits<T>::min(),
101 T max = std::numeric_limits<T>::max()) {
102 return ParseInt(s.c_str(), out, min, max);
103}
104
Elliott Hughes7dd8e202015-09-04 16:26:51 -0700105} // namespace base
106} // namespace android
107
Elliott Hughesf5224432016-03-23 15:04:52 -0700108#endif // ANDROID_BASE_PARSEINT_H