OR-Tools  9.6
numbers.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 
17 #include "ortools/base/numbers.h"
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"
30 #include "ortools/base/strtoint.h"
31 
32 namespace strings {
33 
34 inline int64_t strtoint64(const char* nptr, char** endptr, int base) {
35  return std::strtoll(nptr, endptr, base); // NOLINT
36 }
37 
38 inline uint64_t strtouint64(const char* nptr, char** endptr, int base) {
39  return std::strtoull(nptr, endptr, base); // NOLINT
40 }
41 
42 inline int32_t strtoint32(const char* nptr, char** endptr, int base) {
43  return std::strtol(nptr, endptr, base); // NOLINT
44 }
45 
46 inline 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 
58 int32_t ParseLeadingInt32Value(const char* str, int32_t deflt) {
59  using std::numeric_limits;
60 
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.
66  } else if (value < numeric_limits<int32_t>::min()) {
68  }
69  return (error == str) ? deflt : value;
70 }
71 
72 uint32_t ParseLeadingUInt32Value(const char* str, uint32_t deflt) {
73  using std::numeric_limits;
74 
75  if (numeric_limits<unsigned long>::max() == // NOLINT
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);
90  value < -static_cast<int64_t>(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 
107 int32_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.
115  } else if (value < numeric_limits<int32_t>::min()) {
117  }
118  return (error == str) ? deflt : value;
119 }
120 
121 uint32_t ParseLeadingUDec32Value(const char* str, uint32_t deflt) {
122  using std::numeric_limits;
123 
124  if (numeric_limits<unsigned long>::max() == // NOLINT
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);
139  value < -static_cast<int64_t>(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 // --------------------------------------------------------------------
155 uint64_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 
161 int64_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 
167 uint64_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 
182 int64_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 
188 uint64_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 
200 double 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  }
210 }
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 // --------------------------------------------------------------------
219 bool 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 max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
int64_t value
Definition: case.cc:32
uint64_t ParseLeadingUDec64Value(const char *str, uint64_t deflt)
Definition: numbers.cc:188
uint32_t ParseLeadingUDec32Value(const char *str, uint32_t deflt)
Definition: numbers.cc:121
bool ParseLeadingBoolValue(const char *str, bool deflt)
Definition: numbers.cc:219
int64_t ParseLeadingInt64Value(const char *str, int64_t deflt)
Definition: numbers.cc:161
uint64_t ParseLeadingHex64Value(const char *str, uint64_t deflt)
Definition: numbers.cc:167
int32_t ParseLeadingInt32Value(const char *str, int32_t deflt)
Definition: numbers.cc:58
int64_t ParseLeadingDec64Value(const char *str, int64_t deflt)
Definition: numbers.cc:182
int32_t ParseLeadingDec32Value(const char *str, int32_t deflt)
Definition: numbers.cc:107
uint32_t ParseLeadingUInt32Value(const char *str, uint32_t deflt)
Definition: numbers.cc:72
int64_t strtoint64(const char *nptr, char **endptr, int base)
Definition: numbers.cc:34
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
double ParseLeadingDoubleValue(const char *str, double deflt)
Definition: numbers.cc:200
int32_t strtoint32(const char *nptr, char **endptr, int base)
Definition: numbers.cc:42
uint64_t ParseLeadingUInt64Value(const char *str, uint64_t deflt)
Definition: numbers.cc:155