Line data Source code
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 : 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 : // snapdev 46 : // 47 : #include <snapdev/trim_string.h> 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 : 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 : 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 260 : for(auto r : length_list) 101 : { 102 218 : std::string::size_type const pos(r.find("...")); 103 218 : if(pos == std::string::npos) 104 : { 105 195 : 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 194 : range.f_maximum = range.f_minimum; 116 : } 117 : else 118 : { 119 69 : std::string const min_value(snapdev::trim_string(r.substr(0, pos))); 120 23 : if(!min_value.empty()) 121 : { 122 23 : if(!validator_integer::convert_string(min_value, range.f_minimum)) 123 : { 124 2 : cppthread::log << cppthread::log_level_t::error 125 1 : << min_value 126 : << " is not a valid value for your range's start;" 127 : " it must only be digits, optionally preceeded by a sign (+ or -)" 128 1 : " and not overflow an int64_t value." 129 2 : << cppthread::end; 130 1 : continue; 131 : } 132 : } 133 : 134 66 : std::string const max_value(snapdev::trim_string(r.substr(pos + 3))); 135 22 : if(!max_value.empty()) 136 : { 137 22 : if(!validator_integer::convert_string(max_value, range.f_maximum)) 138 : { 139 2 : cppthread::log << cppthread::log_level_t::error 140 1 : << max_value 141 : << " is not a valid value for your range's end;" 142 : " it must only be digits, optionally preceeded by a sign (+ or -)" 143 1 : " and not overflow an int64_t value." 144 2 : << cppthread::end; 145 1 : continue; 146 : } 147 : } 148 : 149 21 : if(range.f_minimum > range.f_maximum) 150 : { 151 2 : cppthread::log << cppthread::log_level_t::error 152 1 : << min_value 153 1 : << " has to be smaller or equal to " 154 1 : << max_value 155 1 : << "; you have an invalid range." 156 2 : << cppthread::end; 157 1 : continue; 158 : } 159 25 : } 160 214 : f_allowed_lengths.push_back(range); 161 218 : } 162 42 : } 163 : 164 : 165 : /** \brief Return the name of this validator. 166 : * 167 : * This function returns "length". 168 : * 169 : * \return "length". 170 : */ 171 41 : std::string validator_length::name() const 172 : { 173 41 : return std::string("length"); 174 : } 175 : 176 : 177 : /** \brief Check the value against a list of length ranges. 178 : * 179 : * This function is used to verify the length of \p value in characters. 180 : * 181 : * \param[in] value The value to be validated. 182 : * 183 : * \return true on a match. 184 : */ 185 1194 : bool validator_length::validate(std::string const & value) const 186 : { 187 1194 : if(f_allowed_lengths.empty()) 188 : { 189 4 : return true; 190 : } 191 : 192 : // get the number of characters assuming the input string is UTF-8 193 : // 194 1190 : std::int64_t const length(static_cast<std::int64_t>(libutf8::u8length(value))); 195 7031 : for(auto f : f_allowed_lengths) 196 : { 197 6213 : if(length >= f.f_minimum 198 3041 : && length <= f.f_maximum) 199 : { 200 372 : return true; 201 : } 202 : } 203 818 : return false; 204 : } 205 : 206 : 207 : 208 : } // namespace advgetopt 209 : // vim: ts=4 sw=4 et