blob: bb54c99b8e89d1420fd82abbd34089cd983c9103 [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 Hughese3c5a2a2018-06-26 17:17:41 -070017#pragma once
Elliott Hughes7dd8e202015-09-04 16:26:51 -070018
19#include <errno.h>
20#include <stdlib.h>
Elliott Hughes06768992018-04-19 19:48:25 -070021#include <string.h>
Elliott Hughes7dd8e202015-09-04 16:26:51 -070022
23#include <limits>
Elliott Hughes31d04db2016-10-11 17:09:00 -070024#include <string>
Elliott Hughes7dd8e202015-09-04 16:26:51 -070025
26namespace android {
27namespace base {
28
Inseob Kim06c19d02018-06-29 18:07:00 +090029// Parses the unsigned decimal or hexadecimal integer in the string 's' and sets
30// 'out' to that value. Optionally allows the caller to define a 'max' beyond
31// which otherwise valid values will be rejected. Returns boolean success; 'out'
Elliott Hughes31d04db2016-10-11 17:09:00 -070032// is untouched if parsing fails.
Elliott Hughes7dd8e202015-09-04 16:26:51 -070033template <typename T>
Elliott Hughes06768992018-04-19 19:48:25 -070034bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
35 bool allow_suffixes = false) {
Yifan Hong6b1e33b2016-10-07 16:48:17 -070036 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
Elliott Hughes7dd8e202015-09-04 16:26:51 -070037 errno = 0;
38 char* end;
Elliott Hughesefa901e2015-11-02 09:01:53 -080039 unsigned long long int result = strtoull(s, &end, base);
Elliott Hughes06768992018-04-19 19:48:25 -070040 if (errno != 0 || end == s) return false;
41 if (*end != '\0') {
42 const char* suffixes = "bkmgtpe";
43 const char* suffix;
44 if (!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) return false;
Elliott Hughes06768992018-04-19 19:48:25 -070045 if (__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) return false;
Elliott Hughes7dd8e202015-09-04 16:26:51 -070046 }
47 if (max < result) {
48 return false;
49 }
Steven Morelandc4f40bf2018-07-20 11:02:47 -070050 if (out != nullptr) {
51 *out = static_cast<T>(result);
52 }
Elliott Hughes7dd8e202015-09-04 16:26:51 -070053 return true;
54}
55
Elliott Hughes31d04db2016-10-11 17:09:00 -070056// TODO: string_view
57template <typename T>
Elliott Hughes06768992018-04-19 19:48:25 -070058bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
59 bool allow_suffixes = false) {
60 return ParseUint(s.c_str(), out, max, allow_suffixes);
61}
62
63template <typename T>
64bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
65 return ParseUint(s, out, max, true);
66}
67
68// TODO: string_view
69template <typename T>
70bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
71 return ParseByteCount(s.c_str(), out, max);
Elliott Hughes31d04db2016-10-11 17:09:00 -070072}
73
Inseob Kim06c19d02018-06-29 18:07:00 +090074// Parses the signed decimal or hexadecimal integer in the string 's' and sets
75// 'out' to that value. Optionally allows the caller to define a 'min' and 'max'
Elliott Hughes7dd8e202015-09-04 16:26:51 -070076// beyond which otherwise valid values will be rejected. Returns boolean
Elliott Hughes31d04db2016-10-11 17:09:00 -070077// success; 'out' is untouched if parsing fails.
Elliott Hughes7dd8e202015-09-04 16:26:51 -070078template <typename T>
79bool ParseInt(const char* s, T* out,
80 T min = std::numeric_limits<T>::min(),
81 T max = std::numeric_limits<T>::max()) {
Yifan Hong6b1e33b2016-10-07 16:48:17 -070082 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
Elliott Hughes7dd8e202015-09-04 16:26:51 -070083 errno = 0;
84 char* end;
Elliott Hughesefa901e2015-11-02 09:01:53 -080085 long long int result = strtoll(s, &end, base);
Elliott Hughes7dd8e202015-09-04 16:26:51 -070086 if (errno != 0 || s == end || *end != '\0') {
87 return false;
88 }
89 if (result < min || max < result) {
90 return false;
91 }
Steven Morelandc4f40bf2018-07-20 11:02:47 -070092 if (out != nullptr) {
93 *out = static_cast<T>(result);
94 }
Elliott Hughes7dd8e202015-09-04 16:26:51 -070095 return true;
96}
97
Elliott Hughes31d04db2016-10-11 17:09:00 -070098// TODO: string_view
99template <typename T>
100bool ParseInt(const std::string& s, T* out,
101 T min = std::numeric_limits<T>::min(),
102 T max = std::numeric_limits<T>::max()) {
103 return ParseInt(s.c_str(), out, min, max);
104}
105
Elliott Hughes7dd8e202015-09-04 16:26:51 -0700106} // namespace base
107} // namespace android