advgetopt 2.0.49
Parse complex command line arguments and configuration files in C++.
validator_double.cpp
Go to the documentation of this file.
1// Copyright (c) 2006-2025 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
27// self
28//
30
31
32// cppthread
33//
34#include <cppthread/log.h>
35
36
37// snapdev
38//
39#include <snapdev/trim_string.h>
40
41
42// last include
43//
44#include <snapdev/poison.h>
45
46
47
48
49namespace advgetopt
50{
51
52
53
54namespace
55{
56
57
59 : public validator_factory
60{
61public:
63 {
64 validator::register_validator(*this);
65 }
66
67 virtual std::string get_name() const override
68 {
69 return std::string("double");
70 }
71
72 virtual std::shared_ptr<validator> create(string_list_t const & data) const override
73 {
74 return std::make_shared<validator_double>(data);
75 }
76};
77
79
80
81} // no name namespace
82
83
84
85
132{
133 for(auto r : range_list)
134 {
136 std::string::size_type const pos(r.find("..."));
137 if(pos == std::string::npos)
138 {
139 if(!convert_string(r, range.f_minimum))
140 {
141 cppthread::log << cppthread::log_level_t::error
142 << r
143 << " is not a valid standalone value;"
144 " it must be a valid floating point,"
145 " optionally preceded by a sign (+ or -)."
146 << cppthread::end;
147 continue;
148 }
149 range.f_maximum = range.f_minimum;
150 }
151 else
152 {
153 std::string const min_value(snapdev::trim_string(r.substr(0, pos)));
154 if(!min_value.empty())
155 {
156 if(!convert_string(min_value, range.f_minimum))
157 {
158 cppthread::log << cppthread::log_level_t::error
159 << min_value
160 << " is not a valid value for your range's start;"
161 " it must be a valid floating point,"
162 " optionally preceded by a sign (+ or -)."
163 << cppthread::end;
164 continue;
165 }
166 }
167
168 std::string const max_value(snapdev::trim_string(r.substr(pos + 3)));
169 if(!max_value.empty())
170 {
171 if(!convert_string(max_value, range.f_maximum))
172 {
173 cppthread::log << cppthread::log_level_t::error
174 << max_value
175 << " is not a valid value for your range's end;"
176 " it must be a valid floating point,"
177 " optionally preceded by a sign (+ or -)."
178 << cppthread::end;
179 continue;
180 }
181 }
182
183 if(range.f_minimum > range.f_maximum)
184 {
185 cppthread::log << cppthread::log_level_t::error
186 << min_value
187 << " has to be smaller or equal to "
188 << max_value
189 << "; you have an invalid range."
190 << cppthread::end;
191 continue;
192 }
193 }
194 f_allowed_values.push_back(range);
195 }
196}
197
198
205std::string validator_double::name() const
206{
207 return std::string("double");
208}
209
210
228bool validator_double::validate(std::string const & value) const
229{
230 double result(0.0);
231 if(convert_string(value, result))
232 {
233 if(f_allowed_values.empty())
234 {
235 return true;
236 }
237
238 for(auto f : f_allowed_values)
239 {
240 if(result >= f.f_minimum
241 && result <= f.f_maximum)
242 {
243 return true;
244 }
245 }
246 set_error("out of range.");
247 return false;
248 }
249
250 set_error("not a valid floating point number.");
251 return false;
252}
253
254
273bool validator_double::convert_string(std::string const & value, double & result)
274{
275 char const * start(value.c_str());
276
277 // do not allow spaces before the number
278 //
279 if(start[0] != '+'
280 && start[0] != '-'
281 && (start[0] < '0' || start[0] > '9'))
282 {
283 return false;
284 }
285
286 char * end(nullptr);
287 errno = 0;
288 result = std::strtod(start, &end);
289
290 // do not allow anything after the last digit
291 // also return false on an overflow
292 //
293 return end == start + value.length()
294 && errno != ERANGE;
295}
296
297
298
299} // namespace advgetopt
300// 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 a double.
virtual std::string name() const override
Return the name of this validator.
range_t::vector_t f_allowed_values
static bool convert_string(std::string const &number, double &result)
Convert a string to a double value.
validator_double(string_list_t const &data)
Initialize the double validator.
void set_error(std::string const &msg) const
The advgetopt environment to parse command line options.
Definition version.h:37
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.