Line data Source code
1 : // Copyright (c) 2006-2022 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 :
20 : /** \file
21 : * \brief Implementation of the length validator.
22 : *
23 : * The length validator allows us to check the number of characters in the
24 : * value. If less than the minimum or more than the maximum, then it is not
25 : * considered valid.
26 : */
27 :
28 : // self
29 : //
30 : #include "advgetopt/validator_length.h"
31 :
32 : #include "advgetopt/validator_integer.h"
33 :
34 :
35 : // cppthread
36 : //
37 : #include <cppthread/log.h>
38 :
39 :
40 : // libutf8
41 : //
42 : #include <libutf8/libutf8.h>
43 :
44 :
45 : // boost
46 : //
47 : #include <boost/algorithm/string/trim.hpp>
48 :
49 :
50 : // last include
51 : //
52 : #include <snapdev/poison.h>
53 :
54 :
55 :
56 :
57 : namespace advgetopt
58 : {
59 :
60 :
61 :
62 : namespace
63 : {
64 :
65 :
66 :
67 2 : class validator_length_factory
68 : : public validator_factory
69 : {
70 : public:
71 2 : validator_length_factory()
72 2 : {
73 2 : validator::register_validator(*this);
74 2 : }
75 :
76 4 : virtual std::string get_name() const override
77 : {
78 4 : return std::string("length");
79 : }
80 :
81 42 : virtual std::shared_ptr<validator> create(string_list_t const & data) const override
82 : {
83 42 : return std::make_shared<validator_length>(data);
84 : }
85 : };
86 :
87 2 : validator_length_factory g_validator_length_factory;
88 :
89 :
90 :
91 : } // no name namespace
92 :
93 :
94 :
95 :
96 :
97 42 : validator_length::validator_length(string_list_t const & length_list)
98 : {
99 42 : range_t range;
100 249 : for(auto r : length_list)
101 : {
102 211 : std::string::size_type const pos(r.find("..."));
103 211 : if(pos == std::string::npos)
104 : {
105 189 : if(!validator_integer::convert_string(r, range.f_minimum))
106 : {
107 2 : cppthread::log << cppthread::log_level_t::error
108 1 : << r
109 : << " is not a valid standalone value for your ranges;"
110 : " it must only be digits, optionally preceeded by a sign (+ or -)"
111 1 : " and not overflow an int64_t value."
112 2 : << cppthread::end;
113 1 : continue;
114 : }
115 187 : range.f_maximum = range.f_minimum;
116 : }
117 : else
118 : {
119 43 : std::string min_value(r.substr(0, pos));
120 23 : boost::trim(min_value);
121 24 : if(!validator_integer::convert_string(min_value, range.f_minimum))
122 : {
123 2 : cppthread::log << cppthread::log_level_t::error
124 1 : << min_value
125 : << " is not a valid value for your range's start;"
126 : " it must only be digits, optionally preceeded by a sign (+ or -)"
127 1 : " and not overflow an int64_t value."
128 2 : << cppthread::end;
129 1 : continue;
130 : }
131 :
132 42 : std::string max_value(r.substr(pos + 3));
133 22 : boost::trim(max_value);
134 23 : if(!validator_integer::convert_string(max_value, range.f_maximum))
135 : {
136 2 : cppthread::log << cppthread::log_level_t::error
137 1 : << max_value
138 : << " is not a valid value for your range's end;"
139 : " it must only be digits, optionally preceeded by a sign (+ or -)"
140 1 : " and not overflow an int64_t value."
141 2 : << cppthread::end;
142 1 : continue;
143 : }
144 :
145 22 : if(range.f_minimum > range.f_maximum)
146 : {
147 2 : cppthread::log << cppthread::log_level_t::error
148 1 : << min_value
149 1 : << " has to be smaller or equal to "
150 1 : << max_value
151 1 : << "; you have an invalid range."
152 2 : << cppthread::end;
153 1 : continue;
154 : }
155 : }
156 207 : f_allowed_lengths.push_back(range);
157 : }
158 42 : }
159 :
160 :
161 : /** \brief Return the name of this validator.
162 : *
163 : * This function returns "length".
164 : *
165 : * \return "length".
166 : */
167 41 : std::string validator_length::name() const
168 : {
169 41 : return std::string("length");
170 : }
171 :
172 :
173 : /** \brief Check the value against a list of length ranges.
174 : *
175 : * This function is used to verify the length of \p value in characters.
176 : *
177 : * \param[in] value The value to be validated.
178 : *
179 : * \return true on a match.
180 : */
181 1245 : bool validator_length::validate(std::string const & value) const
182 : {
183 1245 : if(f_allowed_lengths.empty())
184 : {
185 4 : return true;
186 : }
187 :
188 : // get the number of characters assuming the input string is UTF-8
189 : //
190 1241 : std::int64_t const length(static_cast<std::int64_t>(libutf8::u8length(value)));
191 6941 : for(auto f : f_allowed_lengths)
192 : {
193 6100 : if(length >= f.f_minimum
194 2953 : && length <= f.f_maximum)
195 : {
196 400 : return true;
197 : }
198 : }
199 841 : return false;
200 : }
201 :
202 :
203 :
204 6 : } // namespace advgetopt
205 : // vim: ts=4 sw=4 et
|