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