Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
numbers.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// This file contains std::string processing functions related to
15// numeric values.
16
18
19#include <errno.h> // for errno
20
21#include <cstdint>
22#include <cstdlib>
23#include <limits>
24
25#include "absl/strings/ascii.h"
26
27namespace strings {
28
29inline int64_t strtoint64(const char* nptr, char** endptr, int base) {
30 return std::strtoll(nptr, endptr, base); // NOLINT
31}
32
33inline uint64_t strtouint64(const char* nptr, char** endptr, int base) {
34 return std::strtoull(nptr, endptr, base); // NOLINT
35}
36
37inline int32_t strtoint32(const char* nptr, char** endptr, int base) {
38 return std::strtol(nptr, endptr, base); // NOLINT
39}
40
41inline uint32_t strtouint32(const char* nptr, char** endptr, int base) {
42 return std::strtoul(nptr, endptr, base); // NOLINT
43}
44
45// ----------------------------------------------------------------------
46// ParseLeadingInt32Value()
47// ParseLeadingUInt32Value()
48// A simple parser for [u]int32_t values. Returns the parsed value
49// if a valid value is found; else returns deflt
50// This cannot handle decimal numbers with leading 0s.
51// --------------------------------------------------------------------
52
53int32_t ParseLeadingInt32Value(const char* str, int32_t deflt) {
54 using std::numeric_limits;
56 char* error = nullptr;
57 long value = strtol(str, &error, 0); // NOLINT
58 // Limit long values to int32_t min/max. Needed for lp64; no-op on 32 bits.
59 if (value > numeric_limits<int32_t>::max()) {
60 value = numeric_limits<int32_t>::max();
61 } else if (value < numeric_limits<int32_t>::min()) {
62 value = numeric_limits<int32_t>::min();
63 }
64 return (error == str) ? deflt : value;
65}
66
67uint32_t ParseLeadingUInt32Value(const char* str, uint32_t deflt) {
68 using std::numeric_limits;
70 if (numeric_limits<unsigned long>::max() == // NOLINT
71 numeric_limits<uint32_t>::max()) {
72 // When long is 32 bits, we can use strtoul.
73 char* error = nullptr;
74 const uint32_t value = strtoul(str, &error, 0); // NOLINT
75 return (error == str) ? deflt : value;
76 } else {
77 // When long is 64 bits, we must use strtoint64 and handle limits
78 // by hand. The reason we cannot use a 64-bit strtoul is that
79 // it would be impossible to differentiate "-2" (that should wrap
80 // around to the value UINT_MAX-1) from a std::string with ULONG_MAX-1
81 // (that should be pegged to UINT_MAX due to overflow).
82 char* error = nullptr;
83 int64_t value = strtoint64(str, &error, 0);
84 if (value > numeric_limits<uint32_t>::max() ||
85 value < -static_cast<int64_t>(numeric_limits<uint32_t>::max())) {
86 value = numeric_limits<uint32_t>::max();
87 }
88 // Within these limits, truncation to 32 bits handles negatives correctly.
89 return (error == str) ? deflt : value;
90 }
91}
92
93// ----------------------------------------------------------------------
94// ParseLeadingDec32Value
95// ParseLeadingUDec32Value
96// A simple parser for [u]int32_t values. Returns the parsed value
97// if a valid value is found; else returns deflt
98// The std::string passed in is treated as *10 based*.
99// This can handle strings with leading 0s.
100// --------------------------------------------------------------------
101
102int32_t ParseLeadingDec32Value(const char* str, int32_t deflt) {
103 using std::numeric_limits;
104
105 char* error = nullptr;
106 long value = strtol(str, &error, 10); // NOLINT
107 // Limit long values to int32_t min/max. Needed for lp64; no-op on 32 bits.
108 if (value > numeric_limits<int32_t>::max()) {
109 value = numeric_limits<int32_t>::max();
110 } else if (value < numeric_limits<int32_t>::min()) {
111 value = numeric_limits<int32_t>::min();
112 }
113 return (error == str) ? deflt : value;
114}
115
116uint32_t ParseLeadingUDec32Value(const char* str, uint32_t deflt) {
117 using std::numeric_limits;
118
119 if (numeric_limits<unsigned long>::max() == // NOLINT
120 numeric_limits<uint32_t>::max()) {
121 // When long is 32 bits, we can use strtoul.
122 char* error = nullptr;
123 const uint32_t value = strtoul(str, &error, 10); // NOLINT
124 return (error == str) ? deflt : value;
125 } else {
126 // When long is 64 bits, we must use strtoint64 and handle limits
127 // by hand. The reason we cannot use a 64-bit strtoul is that
128 // it would be impossible to differentiate "-2" (that should wrap
129 // around to the value UINT_MAX-1) from a std::string with ULONG_MAX-1
130 // (that should be pegged to UINT_MAX due to overflow).
131 char* error = nullptr;
132 int64_t value = strtoint64(str, &error, 10);
133 if (value > numeric_limits<uint32_t>::max() ||
134 value < -static_cast<int64_t>(numeric_limits<uint32_t>::max())) {
135 value = numeric_limits<uint32_t>::max();
136 }
137 // Within these limits, truncation to 32 bits handles negatives correctly.
138 return (error == str) ? deflt : value;
139 }
140}
141
142// ----------------------------------------------------------------------
143// ParseLeadingUInt64Value
144// ParseLeadingInt64Value
145// ParseLeadingHex64Value
146// A simple parser for 64-bit values. Returns the parsed value if a
147// valid integer is found; else returns deflt
148// Uint64_t and int64_t cannot handle decimal numbers with leading 0s.
149// --------------------------------------------------------------------
150uint64_t ParseLeadingUInt64Value(const char* str, uint64_t deflt) {
151 char* error = nullptr;
152 const uint64_t value = strtouint64(str, &error, 0);
153 return (error == str) ? deflt : value;
154}
155
156int64_t ParseLeadingInt64Value(const char* str, int64_t deflt) {
157 char* error = nullptr;
158 const int64_t value = strtoint64(str, &error, 0);
159 return (error == str) ? deflt : value;
160}
161
162uint64_t ParseLeadingHex64Value(const char* str, uint64_t deflt) {
163 char* error = nullptr;
164 const uint64_t value = strtouint64(str, &error, 16);
165 return (error == str) ? deflt : value;
166}
167
168// ----------------------------------------------------------------------
169// ParseLeadingDec64Value
170// ParseLeadingUDec64Value
171// A simple parser for [u]int64_t values. Returns the parsed value
172// if a valid value is found; else returns deflt
173// The std::string passed in is treated as *10 based*.
174// This can handle strings with leading 0s.
175// --------------------------------------------------------------------
176
177int64_t ParseLeadingDec64Value(const char* str, int64_t deflt) {
178 char* error = nullptr;
179 const int64_t value = strtoint64(str, &error, 10);
180 return (error == str) ? deflt : value;
181}
182
183uint64_t ParseLeadingUDec64Value(const char* str, uint64_t deflt) {
184 char* error = nullptr;
185 const uint64_t value = strtouint64(str, &error, 10);
186 return (error == str) ? deflt : value;
187}
188
189// ----------------------------------------------------------------------
190// ParseLeadingDoubleValue()
191// A simple parser for double values. Returns the parsed value
192// if a valid value is found; else returns deflt
193// --------------------------------------------------------------------
194
195double ParseLeadingDoubleValue(const char* str, double deflt) {
196 char* error = nullptr;
197 errno = 0;
198 const double value = strtod(str, &error);
199 if (errno != 0 || // overflow/underflow happened
200 error == str) { // no valid parse
201 return deflt;
202 } else {
203 return value;
204 }
206
207// ----------------------------------------------------------------------
208// ParseLeadingBoolValue()
209// A recognizer of boolean std::string values. Returns the parsed value
210// if a valid value is found; else returns deflt. This skips leading
211// whitespace, is case insensitive, and recognizes these forms:
212// 0/1, false/true, no/yes, n/y
213// --------------------------------------------------------------------
214bool ParseLeadingBoolValue(const char* str, bool deflt) {
215 static const int kMaxLen = 5;
216 char value[kMaxLen + 1];
217 // Skip whitespace
218 while (absl::ascii_isspace(*str)) {
219 ++str;
220 }
221 int len = 0;
222 for (; len <= kMaxLen && absl::ascii_isalnum(*str); ++str) {
223 value[len++] = absl::ascii_tolower(*str);
224 }
225 if (len == 0 || len > kMaxLen) return deflt;
226 value[len] = '\0';
227 switch (len) {
228 case 1:
229 if (value[0] == '0' || value[0] == 'n') return false;
230 if (value[0] == '1' || value[0] == 'y') return true;
231 break;
232 case 2:
233 if (!strcmp(value, "no")) return false;
234 break;
235 case 3:
236 if (!strcmp(value, "yes")) return true;
237 break;
238 case 4:
239 if (!strcmp(value, "true")) return true;
240 break;
241 case 5:
242 if (!strcmp(value, "false")) return false;
243 break;
244 }
245 return deflt;
246}
247} // namespace strings
Convert strings to numbers or numbers to strings.
Definition case.cc:32
uint64_t ParseLeadingUInt64Value(const char *str, uint64_t deflt)
Definition numbers.cc:156
uint64_t ParseLeadingUDec64Value(const char *str, uint64_t deflt)
Definition numbers.cc:191
double ParseLeadingDoubleValue(const char *str, double deflt)
Definition numbers.cc:205
int32_t ParseLeadingDec32Value(const char *str, int32_t deflt)
Definition numbers.cc:106
int64_t ParseLeadingDec64Value(const char *str, int64_t deflt)
Definition numbers.cc:185
int64_t strtoint64(const char *nptr, char **endptr, int base)
Definition numbers.cc:29
uint32_t ParseLeadingUDec32Value(const char *str, uint32_t deflt)
Definition numbers.cc:120
uint64_t strtouint64(const char *nptr, char **endptr, int base)
Definition numbers.cc:33
uint32_t strtouint32(const char *nptr, char **endptr, int base)
Definition numbers.cc:41
int32_t ParseLeadingInt32Value(const char *str, int32_t deflt)
Definition numbers.cc:55
false no n y bool ParseLeadingBoolValue(const char *str, bool deflt)
Definition numbers.cc:226
uint64_t ParseLeadingHex64Value(const char *str, uint64_t deflt)
Definition numbers.cc:168
int32_t strtoint32(const char *nptr, char **endptr, int base)
Definition numbers.cc:37
uint32_t ParseLeadingUInt32Value(const char *str, uint32_t deflt)
Definition numbers.cc:69
int64_t ParseLeadingInt64Value(const char *str, int64_t deflt)
Definition numbers.cc:162