advgetopt 2.0.47
Parse complex command line arguments and configuration files in C++.
validator_integer.cpp
Go to the documentation of this file.
1// Copyright (c) 2006-2024 Made to Order Software Corp. All Rights Reserved
2//
3// https://snapwebsites.org/project/advgetopt
4// contact@m2osw.com
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License along
17// with this program; if not, write to the Free Software Foundation, Inc.,
18// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
44// self
45//
47
48
49// cppthread
50//
51#include <cppthread/log.h>
52
53
54// snapdev
55//
56#include <snapdev/trim_string.h>
57
58
59// last include
60//
61#include <snapdev/poison.h>
62
63
64
65
66namespace advgetopt
67{
68
69
70
71namespace
72{
73
74
75
77 : public validator_factory
78{
79public:
81 {
82 validator::register_validator(*this);
83 }
84
85 virtual std::string get_name() const override
86 {
87 return std::string("integer");
88 }
89
90 virtual std::shared_ptr<validator> create(string_list_t const & data) const override
91 {
92 return std::make_shared<validator_integer>(data);
93 }
94};
95
97
98
99
100} // no name namespace
101
102
103
104
105
152{
154 for(auto r : range_list)
155 {
156 std::string::size_type const pos(r.find("..."));
157 if(pos == std::string::npos)
158 {
159 if(!convert_string(r, range.f_minimum))
160 {
161 cppthread::log << cppthread::log_level_t::error
162 << r
163 << " is not a valid standalone value for your ranges;"
164 " it must only be digits, optionally preceeded by a sign (+ or -)"
165 " and not overflow an int64_t value."
166 << cppthread::end;
167 continue;
168 }
169 range.f_maximum = range.f_minimum;
170 }
171 else
172 {
173 std::string const min_value(snapdev::trim_string(r.substr(0, pos)));
174 if(!min_value.empty())
175 {
176 if(!convert_string(min_value, range.f_minimum))
177 {
178 cppthread::log << cppthread::log_level_t::error
179 << min_value
180 << " is not a valid value for your range's start;"
181 " it must only be digits, optionally preceeded by a sign (+ or -)"
182 " and not overflow an int64_t value."
183 << cppthread::end;
184 continue;
185 }
186 }
187
188 std::string const max_value(snapdev::trim_string(r.substr(pos + 3)));
189 if(!max_value.empty())
190 {
191 if(!convert_string(max_value, range.f_maximum))
192 {
193 cppthread::log << cppthread::log_level_t::error
194 << max_value
195 << " is not a valid value for your range's end;"
196 " it must only be digits, optionally preceeded by a sign (+ or -)"
197 " and not overflow an int64_t value."
198 << cppthread::end;
199 continue;
200 }
201 }
202
203 if(range.f_minimum > range.f_maximum)
204 {
205 cppthread::log << cppthread::log_level_t::error
206 << min_value
207 << " has to be smaller or equal to "
208 << max_value
209 << "; you have an invalid range."
210 << cppthread::end;
211 continue;
212 }
213 }
214 f_allowed_values.push_back(range);
215 }
216}
217
218
225std::string validator_integer::name() const
226{
227 return std::string("integer");
228}
229
230
250bool validator_integer::validate(std::string const & value) const
251{
252 std::int64_t result(0);
253 if(convert_string(value, result))
254 {
255 if(f_allowed_values.empty())
256 {
257 return true;
258 }
259
260 for(auto f : f_allowed_values)
261 {
262 if(result >= f.f_minimum
263 && result <= f.f_maximum)
264 {
265 return true;
266 }
267 }
268 return false;
269 }
270
271 return false;
272}
273
274
289bool validator_integer::convert_string(std::string const & value, std::int64_t & result)
290{
291 std::uint64_t integer(0);
292 char const * s(value.c_str());
293
294 char sign('\0');
295 if(*s == '-' || *s == '+')
296 {
297 sign = *s;
298 ++s;
299 }
300
301 int base(10);
302 if(*s == '0')
303 {
304 if(s[1] == 'b')
305 {
306 base = 2;
307 s += 2;
308 }
309 else if(s[1] == 'd')
310 {
311 //base = 10; -- this is the default
312 s += 2;
313 }
314 else if(s[1] == 'o')
315 {
316 base = 8;
317 s += 2;
318 }
319 else if(s[1] == 'x')
320 {
321 base = 16;
322 s += 2;
323 }
324 // else start from 's' (including the '0')
325 }
326
327 if(*s == '\0')
328 {
329 // empty string or just the introducer, not considered valid
330 //
331 return false;
332 }
333
334 for(;;)
335 {
336 char const c(*s++);
337 if(c == '\0')
338 {
339 // valid
340 //
341 if(sign == '-')
342 {
343 if(integer > 0x8000000000000000ULL)
344 {
345 return false;
346 }
347 result = -integer;
348 }
349 else
350 {
351 if(integer > 0x7FFFFFFFFFFFFFFFULL)
352 {
353 return false;
354 }
355 result = integer;
356 }
357 return true;
358 }
359
360 std::int64_t digit(std::numeric_limits<std::int64_t>::max());
361 if(c >= '0' && c <= '9')
362 {
363 digit = c - '0';
364 }
365 else if(c >= 'a' && c <= 'f')
366 {
367 digit = c - ('a' - 10);
368 }
369 else if(c >= 'A' && c <= 'F')
370 {
371 digit = c - ('A' - 10);
372 }
373 if(digit >= base)
374 {
375 // invalid digit
376 //
377 return false;
378 }
379
380 std::uint64_t const old(integer);
382 if(integer < old)
383 {
384 // overflow
385 //
386 return false;
387 }
388 }
389}
390
391
392
393} // namespace advgetopt
394// vim: ts=4 sw=4 et
virtual std::shared_ptr< validator > create(string_list_t const &data) const override
virtual bool validate(std::string const &value) const override
Determine whether value is an integer.
static bool convert_string(std::string const &number, std::int64_t &result)
Convert a string to an std::int64_t value.
validator_integer(string_list_t const &data)
Initialize the integer validator.
virtual std::string name() const override
Return the name of this validator.
The advgetopt environment to parse command line options.
constexpr flag_t option_flags_merge()
Definition flags.h:87
std::vector< std::string > string_list_t
Definition utils.h:41
Declaration of validators which can be used to verify the parameters.

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.