Android-cuttlefish cvd tool
parseint.h
Go to the documentation of this file.
1/*
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
17#pragma once
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <limits>
24#include <string>
25#include <type_traits>
26
27namespace android {
28namespace base {
29
30// Parses the unsigned decimal or hexadecimal integer in the string 's' and sets
31// 'out' to that value if it is specified. Optionally allows the caller to define
32// a 'max' beyond which otherwise valid values will be rejected. Returns boolean
33// success; 'out' is untouched if parsing fails.
34template <typename T>
35bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
36 bool allow_suffixes = false) {
37 static_assert(std::is_unsigned<T>::value, "ParseUint can only be used with unsigned types");
38 while (isspace(*s)) {
39 s++;
40 }
41
42 if (s[0] == '-') {
43 errno = EINVAL;
44 return false;
45 }
46
47 // This is never out of bounds. If string is zero-sized, s[0] == '\0'
48 // so the second condition is not checked. If string is "0",
49 // s[1] will compare against the '\0'.
50 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
51 errno = 0;
52 char* end;
53 unsigned long long int result = strtoull(s, &end, base);
54 if (errno != 0) return false;
55 if (end == s) {
56 errno = EINVAL;
57 return false;
58 }
59 if (*end != '\0') {
60 const char* suffixes = "bkmgtpe";
61 const char* suffix;
62 if ((!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) ||
63 __builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) {
64 errno = EINVAL;
65 return false;
66 }
67 }
68 if (max < result) {
69 errno = ERANGE;
70 return false;
71 }
72 if (out != nullptr) {
73 *out = static_cast<T>(result);
74 }
75 return true;
76}
77
78// TODO: string_view
79template <typename T>
80bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
81 bool allow_suffixes = false) {
82 return ParseUint(s.c_str(), out, max, allow_suffixes);
83}
84
85template <typename T>
86bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
87 return ParseUint(s, out, max, true);
88}
89
90// TODO: string_view
91template <typename T>
92bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
93 return ParseByteCount(s.c_str(), out, max);
94}
95
96// Parses the signed decimal or hexadecimal integer in the string 's' and sets
97// 'out' to that value if it is specified. Optionally allows the caller to define
98// a 'min' and 'max' beyond which otherwise valid values will be rejected. Returns
99// boolean success; 'out' is untouched if parsing fails.
100template <typename T>
101bool ParseInt(const char* s, T* out,
103 T max = std::numeric_limits<T>::max()) {
104 static_assert(std::is_signed<T>::value, "ParseInt can only be used with signed types");
105 while (isspace(*s)) {
106 s++;
107 }
108
109 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
110 errno = 0;
111 char* end;
112 long long int result = strtoll(s, &end, base);
113 if (errno != 0) {
114 return false;
115 }
116 if (s == end || *end != '\0') {
117 errno = EINVAL;
118 return false;
119 }
120 if (result < min || max < result) {
121 errno = ERANGE;
122 return false;
123 }
124 if (out != nullptr) {
125 *out = static_cast<T>(result);
126 }
127 return true;
128}
129
130// TODO: string_view
131template <typename T>
132bool ParseInt(const std::string& s, T* out,
134 T max = std::numeric_limits<T>::max()) {
135 return ParseInt(s.c_str(), out, min, max);
136}
137
138} // namespace base
139} // namespace android
#define min(a, b)
Definition: ext4_utils.h:44
bool ParseInt(const char *s, T *out, T min=std::numeric_limits< T >::min(), T max=std::numeric_limits< T >::max())
Definition: parseint.h:101
bool ParseByteCount(const char *s, T *out, T max=std::numeric_limits< T >::max())
Definition: parseint.h:86
bool ParseUint(const char *s, T *out, T max=std::numeric_limits< T >::max(), bool allow_suffixes=false)
Definition: parseint.h:35
Definition: map_ptr.h:34