10#include "../Validators.hpp"
12#include "../Encoding.hpp"
13#include "../Macros.hpp"
14#include "../StringTools.hpp"
15#include "../TypeTools.hpp"
27 std::string retstring;
30 std::string value = str;
31 retstring =
func_(value);
33 retstring =
func_(str);
41 newval.desc_function_ = [validator_desc]() {
return validator_desc; };
48 newval._merge_description(*
this, other,
" AND ");
51 const std::function<std::string(std::string & filename)> &f1 =
func_;
52 const std::function<std::string(std::string & filename)> &f2 = other.func_;
54 newval.func_ = [f1, f2](std::string &input) {
55 std::string s1 = f1(input);
56 std::string s2 = f2(input);
57 if(!s1.empty() && !s2.empty())
58 return std::string(
"(") + s1 +
") AND (" + s2 +
")";
62 newval.active_ =
active_ && other.active_;
70 newval._merge_description(*
this, other,
" OR ");
73 const std::function<std::string(std::string &)> &f1 =
func_;
74 const std::function<std::string(std::string &)> &f2 = other.func_;
76 newval.func_ = [f1, f2](std::string &input) {
77 std::string s1 = f1(input);
78 std::string s2 = f2(input);
79 if(s1.empty() || s2.empty())
82 return std::string(
"(") + s1 +
") OR (" + s2 +
")";
84 newval.active_ =
active_ && other.active_;
94 return (!str.empty()) ? std::string(
"NOT ") + str : std::string{};
97 const std::function<std::string(std::string & res)> &f1 =
func_;
99 newval.func_ = [f1, dfunc1](std::string &test) -> std::string {
100 std::string s1 = f1(test);
102 return std::string(
"check ") + dfunc1() +
" succeeded improperly";
104 return std::string{};
112Validator::_merge_description(
const Validator &val1,
const Validator &val2,
const std::string &merger) {
114 const std::function<std::string()> &dfunc1 = val1.desc_function_;
115 const std::function<std::string()> &dfunc2 = val2.desc_function_;
118 std::string f1 = dfunc1();
119 std::string f2 = dfunc2();
120 if((f1.empty()) || (f2.empty())) {
123 return std::string(1,
'(') + f1 +
')' + merger +
'(' + f2 +
')';
129#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
130CLI11_INLINE path_type check_path(
const char *file)
noexcept {
132 auto stat = std::filesystem::status(to_path(file), ec);
134 return path_type::nonexistent;
136 switch(stat.type()) {
137 case std::filesystem::file_type::none:
138 case std::filesystem::file_type::not_found:
139 return path_type::nonexistent;
140 case std::filesystem::file_type::directory:
141 return path_type::directory;
142 case std::filesystem::file_type::symlink:
143 case std::filesystem::file_type::block:
144 case std::filesystem::file_type::character:
145 case std::filesystem::file_type::fifo:
146 case std::filesystem::file_type::socket:
147 case std::filesystem::file_type::regular:
148 case std::filesystem::file_type::unknown:
150 return path_type::file;
154CLI11_INLINE path_type check_path(
const char *file)
noexcept {
156 struct __stat64 buffer;
157 if(_stat64(file, &buffer) == 0) {
158 return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
162 if(stat(file, &buffer) == 0) {
163 return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
166 return path_type::nonexistent;
170CLI11_INLINE ExistingFileValidator::ExistingFileValidator() : Validator(
"FILE") {
171 func_ = [](std::string &filename) {
172 auto path_result = check_path(filename.c_str());
173 if(path_result == path_type::nonexistent) {
174 return "File does not exist: " + filename;
176 if(path_result == path_type::directory) {
177 return "File is actually a directory: " + filename;
179 return std::string();
183CLI11_INLINE ExistingDirectoryValidator::ExistingDirectoryValidator() : Validator(
"DIR") {
184 func_ = [](std::string &filename) {
185 auto path_result = check_path(filename.c_str());
186 if(path_result == path_type::nonexistent) {
187 return "Directory does not exist: " + filename;
189 if(path_result == path_type::file) {
190 return "Directory is actually a file: " + filename;
192 return std::string();
196CLI11_INLINE ExistingPathValidator::ExistingPathValidator() : Validator(
"PATH(existing)") {
197 func_ = [](std::string &filename) {
198 auto path_result = check_path(filename.c_str());
199 if(path_result == path_type::nonexistent) {
200 return "Path does not exist: " + filename;
202 return std::string();
206CLI11_INLINE NonexistentPathValidator::NonexistentPathValidator() : Validator(
"PATH(non-existing)") {
207 func_ = [](std::string &filename) {
208 auto path_result = check_path(filename.c_str());
209 if(path_result != path_type::nonexistent) {
210 return "Path already exists: " + filename;
212 return std::string();
216CLI11_INLINE IPV4Validator::IPV4Validator() : Validator(
"IPV4") {
217 func_ = [](std::string &ip_addr) {
218 auto result = CLI::detail::split(ip_addr,
'.');
219 if(result.size() != 4) {
220 return std::string(
"Invalid IPV4 address must have four parts (") + ip_addr +
')';
223 for(
const auto &var : result) {
224 using CLI::detail::lexical_cast;
225 bool retval = lexical_cast(var, num);
227 return std::string(
"Failed parsing number (") + var +
')';
229 if(num < 0 || num > 255) {
230 return std::string(
"Each IP number must be between 0 and 255 ") + var;
233 return std::string{};
237CLI11_INLINE EscapedStringTransformer::EscapedStringTransformer() {
238 func_ = [](std::string &str) {
240 if(str.size() > 1 && (str.front() ==
'\"' || str.front() ==
'\'' || str.front() ==
'`') &&
241 str.front() == str.back()) {
242 process_quoted_string(str);
243 }
else if(str.find_first_of(
'\\') != std::string::npos) {
244 if(detail::is_binary_escaped_string(str)) {
245 str = detail::extract_binary_string(str);
247 str = remove_escaped_characters(str);
250 return std::string{};
251 }
catch(
const std::invalid_argument &ia) {
252 return std::string(ia.what());
258CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path,
bool enableErrorReturn)
259 : Validator(
"FILE") {
260 func_ = [default_path, enableErrorReturn](std::string &filename) {
261 auto path_result = detail::check_path(filename.c_str());
262 if(path_result == detail::path_type::nonexistent) {
263 std::string test_file_path = default_path;
264 if(default_path.back() !=
'/' && default_path.back() !=
'\\') {
266 test_file_path +=
'/';
268 test_file_path.append(filename);
269 path_result = detail::check_path(test_file_path.c_str());
270 if(path_result == detail::path_type::file) {
271 filename = test_file_path;
273 if(enableErrorReturn) {
274 return "File does not exist: " + filename;
278 return std::string{};
284 description(
"SIZE [b, kb(=1000b), kib(=1024b), ...]");
290CLI11_INLINE std::map<std::string, AsSizeValue::result_t> AsSizeValue::init_mapping(
bool kb_is_1000) {
291 std::map<std::string, result_t> m;
292 result_t k_factor = kb_is_1000 ? 1000 : 1024;
293 result_t ki_factor = 1024;
297 for(std::string p : {
"k",
"m",
"g",
"t",
"p",
"e"}) {
308CLI11_INLINE std::map<std::string, AsSizeValue::result_t> AsSizeValue::get_mapping(
bool kb_is_1000) {
310 static auto m = init_mapping(
true);
313 static auto m = init_mapping(
false);
319CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline) {
321 std::pair<std::string, std::string> vals;
323 auto esp = commandline.find_first_of(
' ', 1);
324 while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) {
325 esp = commandline.find_first_of(
' ', esp + 1);
326 if(esp == std::string::npos) {
329 if(commandline[0] ==
'"' || commandline[0] ==
'\'' || commandline[0] ==
'`') {
330 bool embeddedQuote =
false;
331 auto keyChar = commandline[0];
332 auto end = commandline.find_first_of(keyChar, 1);
333 while((end != std::string::npos) && (commandline[end - 1] ==
'\\')) {
334 end = commandline.find_first_of(keyChar, end + 1);
335 embeddedQuote =
true;
337 if(end != std::string::npos) {
338 vals.first = commandline.substr(1, end - 1);
341 vals.first = find_and_replace(vals.first, std::string(
"\\") + keyChar, std::string(1, keyChar));
344 esp = commandline.find_first_of(
' ', 1);
347 esp = commandline.find_first_of(
' ', 1);
353 if(vals.first.empty()) {
354 vals.first = commandline.substr(0, esp);
359 vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{};
Definition Validators.hpp:718
AsSizeValue(bool kb_is_1000)
Definition Validators_inl.hpp:282
Some validators that are provided.
Definition Validators.hpp:55
Validator operator&(const Validator &other) const
Definition Validators_inl.hpp:45
int application_index_
A Validator will only apply to an indexed value (-1 is all elements)
Definition Validators.hpp:66
Validator & description(std::string validator_desc)
Specify the type string.
Definition Validators.hpp:100
Validator operator|(const Validator &other) const
Definition Validators_inl.hpp:67
bool active_
Enable for Validator to allow it to be disabled if need be.
Definition Validators.hpp:68
bool non_modifying_
specify that a validator should not modify the input
Definition Validators.hpp:70
std::function< std::string()> desc_function_
This is the description function, if empty the description_ will be used.
Definition Validators.hpp:58
std::function< std::string(std::string &)> func_
Definition Validators.hpp:62
Validator operator!() const
Create a validator that fails when a given validator succeeds.
Definition Validators_inl.hpp:89
std::string operator()(std::string &str) const
Definition Validators_inl.hpp:26