10#include "../Validators.hpp"
12#include "../Encoding.hpp"
13#include "../Macros.hpp"
14#include "../StringTools.hpp"
15#include "../TypeTools.hpp"
21#include <system_error>
28CLI11_INLINE Validator::Validator(std::string validator_desc, std::function<std::string(std::string &)> func)
29 : desc_function_([validator_desc]() {
return validator_desc; }), func_(std::move(func)) {}
31CLI11_INLINE Validator::Validator(std::function<std::string(std::string &)> op,
32 std::string validator_desc,
33 std::string validator_name)
34 :
desc_function_([validator_desc]() {
return validator_desc; }), func_(std::move(op)),
35 name_(std::move(validator_name)) {}
38 std::string retstring;
41 std::string value = str;
42 retstring =
func_(value);
44 retstring =
func_(str);
51 std::string value = str;
56 Validator newval(*
this);
57 newval.
desc_function_ = [validator_desc]() {
return validator_desc; };
68CLI11_NODISCARD CLI11_INLINE Validator
Validator::name(std::string validator_name)
const {
69 Validator newval(*
this);
70 newval.
name_ = std::move(validator_name);
75 Validator newval(*
this);
81 Validator newval(*
this);
89 newval._merge_description(*
this, other,
" AND ");
92 const std::function<std::string(std::string & filename)> &f1 =
func_;
93 const std::function<std::string(std::string & filename)> &f2 = other.
func_;
95 newval.
func_ = [f1, f2](std::string &input) {
96 std::string s1 = f1(input);
97 std::string s2 = f2(input);
98 if(!s1.empty() && !s2.empty())
99 return std::string(
"(") + s1 +
") AND (" + s2 +
")";
111 newval._merge_description(*
this, other,
" OR ");
114 const std::function<std::string(std::string &)> &f1 =
func_;
115 const std::function<std::string(std::string &)> &f2 = other.
func_;
117 newval.
func_ = [f1, f2](std::string &input) {
118 std::string s1 = f1(input);
119 std::string s2 = f2(input);
120 if(s1.empty() || s2.empty())
121 return std::string();
123 return std::string(
"(") + s1 +
") OR (" + s2 +
")";
135 return (!str.empty()) ? std::string(
"NOT ") + str : std::string{};
138 const std::function<std::string(std::string & res)> &f1 =
func_;
140 newval.
func_ = [f1, dfunc1](std::string &test) -> std::string {
141 std::string s1 = f1(test);
143 return std::string(
"check ") + dfunc1() +
" succeeded improperly";
145 return std::string{};
153Validator::_merge_description(
const Validator &val1,
const Validator &val2,
const std::string &merger) {
159 std::string f1 = dfunc1();
160 std::string f2 = dfunc2();
161 if((f1.empty()) || (f2.empty())) {
164 return std::string(1,
'(') + f1 +
')' + merger +
'(' + f2 +
')';
170#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
171CLI11_INLINE path_type check_path(
const char *file)
noexcept {
173 auto stat = std::filesystem::status(to_path(file), ec);
175 return path_type::nonexistent;
177 switch(stat.type()) {
178 case std::filesystem::file_type::none:
179 case std::filesystem::file_type::not_found:
180 return path_type::nonexistent;
181 case std::filesystem::file_type::directory:
182 return path_type::directory;
183 case std::filesystem::file_type::symlink:
184 case std::filesystem::file_type::block:
185 case std::filesystem::file_type::character:
186 case std::filesystem::file_type::fifo:
187 case std::filesystem::file_type::socket:
188 case std::filesystem::file_type::regular:
189 case std::filesystem::file_type::unknown:
191 return path_type::file;
195CLI11_INLINE path_type check_path(
const char *file)
noexcept {
197 struct __stat64 buffer;
198 if(_stat64(file, &buffer) == 0) {
199 return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
203 if(stat(file, &buffer) == 0) {
204 return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
207 return path_type::nonexistent;
211CLI11_INLINE ExistingFileValidator::ExistingFileValidator() : Validator(
"FILE") {
212 func_ = [](std::string &filename) -> std::string {
214 return std::string(
"File name is missing.");
216 auto path_result = check_path(filename.c_str());
217 if(path_result == path_type::nonexistent) {
218 return "File does not exist: " + filename;
220 if(path_result == path_type::directory) {
221 return "File is actually a directory: " + filename;
223 return std::string();
227CLI11_INLINE ExistingDirectoryValidator::ExistingDirectoryValidator() :
Validator(
"DIR") {
228 func_ = [](std::string &filename) {
229 auto path_result = check_path(filename.c_str());
230 if(path_result == path_type::nonexistent) {
231 return "Directory does not exist: " + filename;
233 if(path_result == path_type::file) {
234 return "Directory is actually a file: " + filename;
236 return std::string();
240CLI11_INLINE ExistingPathValidator::ExistingPathValidator() :
Validator(
"PATH(existing)") {
241 func_ = [](std::string &filename) {
242 auto path_result = check_path(filename.c_str());
243 if(path_result == path_type::nonexistent) {
244 return "Path does not exist: " + filename;
246 return std::string();
250CLI11_INLINE NonexistentPathValidator::NonexistentPathValidator() :
Validator(
"PATH(non-existing)") {
251 func_ = [](std::string &filename) {
252 auto path_result = check_path(filename.c_str());
253 if(path_result != path_type::nonexistent) {
254 return "Path already exists: " + filename;
256 return std::string();
260CLI11_INLINE EscapedStringTransformer::EscapedStringTransformer() {
261 func_ = [](std::string &str) {
263 if(str.size() > 1 && (str.front() ==
'\"' || str.front() ==
'\'' || str.front() ==
'`') &&
264 str.front() == str.back()) {
265 process_quoted_string(str);
266 }
else if(str.find_first_of(
'\\') != std::string::npos) {
267 if(detail::is_binary_escaped_string(str)) {
268 str = detail::extract_binary_string(str);
270 str = remove_escaped_characters(str);
273 return std::string{};
274 }
catch(
const std::invalid_argument &ia) {
275 return std::string(ia.what());
281CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path,
bool enableErrorReturn)
282 : Validator(
"FILE") {
283 func_ = [default_path, enableErrorReturn](std::string &filename) {
284 auto path_result = detail::check_path(filename.c_str());
285 if(path_result == detail::path_type::nonexistent) {
286 std::string test_file_path = default_path;
287 if(!default_path.empty() && default_path.back() !=
'/' && default_path.back() !=
'\\') {
289 test_file_path +=
'/';
291 test_file_path.append(filename);
292 path_result = detail::check_path(test_file_path.c_str());
293 if(path_result == detail::path_type::file) {
294 filename = test_file_path;
296 if(enableErrorReturn) {
297 return "File does not exist: " + filename;
301 return std::string{};
307CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline) {
309 std::pair<std::string, std::string> vals;
311 auto esp = commandline.find_first_of(
' ', 1);
312 while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) {
313 if(esp == std::string::npos) {
316 if(commandline[0] ==
'"' || commandline[0] ==
'\'' || commandline[0] ==
'`') {
317 bool embeddedQuote =
false;
318 auto keyChar = commandline[0];
319 auto end = commandline.find_first_of(keyChar, 1);
320 while((end != std::string::npos) && (commandline[end - 1] ==
'\\')) {
321 end = commandline.find_first_of(keyChar, end + 1);
322 embeddedQuote =
true;
324 if(end != std::string::npos) {
325 vals.first = commandline.substr(1, end - 1);
328 vals.first = find_and_replace(vals.first, std::string(
"\\") + keyChar, std::string(1, keyChar));
331 esp = commandline.find_first_of(
' ', 1);
334 esp = commandline.find_first_of(
' ', 1);
339 esp = commandline.find_first_of(
' ', esp + 1);
341 if(vals.first.empty()) {
342 vals.first = commandline.substr(0, esp);
347 vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{};
Some validators that are provided.
Definition Validators.hpp:55
Validator operator&(const Validator &other) const
Definition Validators_inl.hpp:86
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:96
Validator operator|(const Validator &other) const
Definition Validators_inl.hpp:108
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
Validator & name(std::string validator_name)
Specify the type string.
Definition Validators.hpp:106
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
CLI11_NODISCARD std::string get_description() const
Generate type description information for the Validator.
Definition Validators_inl.hpp:61
Validator & active(bool active_val=true)
Specify whether the Validator is active or not.
Definition Validators.hpp:115
std::string name_
The name for search purposes of the Validator.
Definition Validators.hpp:64
Validator operator!() const
Create a validator that fails when a given validator succeeds.
Definition Validators_inl.hpp:130
std::string operator()(std::string &str) const
Definition Validators_inl.hpp:37
Validator & application_index(int app_index)
Specify the application index of a validator.
Definition Validators.hpp:128