Commit 7a7e0822dd669960a98ba4fc01f1987d9bf77059

Authored by Daniel Herrera Castro
Committed by Henry Schreiner
1 parent 40485962

[precompile] Split Validators.hpp

CLI11.hpp.in
... ... @@ -60,6 +60,8 @@ namespace {namespace} {{
60 60  
61 61 {validators_hpp}
62 62  
  63 +{validators_inl_hpp}
  64 +
63 65 {formatter_fwd_hpp}
64 66  
65 67 {option_hpp}
... ...
include/CLI/Validators.hpp
... ... @@ -6,6 +6,7 @@
6 6  
7 7 #pragma once
8 8  
  9 +#include "Error.hpp"
9 10 #include "Macros.hpp"
10 11 #include "StringTools.hpp"
11 12 #include "TypeTools.hpp"
... ... @@ -112,18 +113,7 @@ class Validator {
112 113 }
113 114 /// This is the required operator for a Validator - provided to help
114 115 /// users (CLI11 uses the member `func` directly)
115   - std::string operator()(std::string &str) const {
116   - std::string retstring;
117   - if(active_) {
118   - if(non_modifying_) {
119   - std::string value = str;
120   - retstring = func_(value);
121   - } else {
122   - retstring = func_(str);
123   - }
124   - }
125   - return retstring;
126   - }
  116 + std::string operator()(std::string &str) const;
127 117  
128 118 /// This is the required operator for a Validator - provided to help
129 119 /// users (CLI11 uses the member `func` directly)
... ... @@ -138,11 +128,8 @@ class Validator {
138 128 return *this;
139 129 }
140 130 /// Specify the type string
141   - CLI11_NODISCARD Validator description(std::string validator_desc) const {
142   - Validator newval(*this);
143   - newval.desc_function_ = [validator_desc]() { return validator_desc; };
144   - return newval;
145   - }
  131 + CLI11_NODISCARD Validator description(std::string validator_desc) const;
  132 +
146 133 /// Generate type description information for the Validator
147 134 CLI11_NODISCARD std::string get_description() const {
148 135 if(active_) {
... ... @@ -201,91 +188,18 @@ class Validator {
201 188  
202 189 /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the
203 190 /// same.
204   - Validator operator&(const Validator &other) const {
205   - Validator newval;
206   -
207   - newval._merge_description(*this, other, " AND ");
208   -
209   - // Give references (will make a copy in lambda function)
210   - const std::function<std::string(std::string & filename)> &f1 = func_;
211   - const std::function<std::string(std::string & filename)> &f2 = other.func_;
212   -
213   - newval.func_ = [f1, f2](std::string &input) {
214   - std::string s1 = f1(input);
215   - std::string s2 = f2(input);
216   - if(!s1.empty() && !s2.empty())
217   - return std::string("(") + s1 + ") AND (" + s2 + ")";
218   - return s1 + s2;
219   - };
220   -
221   - newval.active_ = active_ && other.active_;
222   - newval.application_index_ = application_index_;
223   - return newval;
224   - }
  191 + Validator operator&(const Validator &other) const;
225 192  
226 193 /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the
227 194 /// same.
228   - Validator operator|(const Validator &other) const {
229   - Validator newval;
230   -
231   - newval._merge_description(*this, other, " OR ");
232   -
233   - // Give references (will make a copy in lambda function)
234   - const std::function<std::string(std::string &)> &f1 = func_;
235   - const std::function<std::string(std::string &)> &f2 = other.func_;
236   -
237   - newval.func_ = [f1, f2](std::string &input) {
238   - std::string s1 = f1(input);
239   - std::string s2 = f2(input);
240   - if(s1.empty() || s2.empty())
241   - return std::string();
242   -
243   - return std::string("(") + s1 + ") OR (" + s2 + ")";
244   - };
245   - newval.active_ = active_ && other.active_;
246   - newval.application_index_ = application_index_;
247   - return newval;
248   - }
  195 + Validator operator|(const Validator &other) const;
249 196  
250 197 /// Create a validator that fails when a given validator succeeds
251   - Validator operator!() const {
252   - Validator newval;
253   - const std::function<std::string()> &dfunc1 = desc_function_;
254   - newval.desc_function_ = [dfunc1]() {
255   - auto str = dfunc1();
256   - return (!str.empty()) ? std::string("NOT ") + str : std::string{};
257   - };
258   - // Give references (will make a copy in lambda function)
259   - const std::function<std::string(std::string & res)> &f1 = func_;
260   -
261   - newval.func_ = [f1, dfunc1](std::string &test) -> std::string {
262   - std::string s1 = f1(test);
263   - if(s1.empty()) {
264   - return std::string("check ") + dfunc1() + " succeeded improperly";
265   - }
266   - return std::string{};
267   - };
268   - newval.active_ = active_;
269   - newval.application_index_ = application_index_;
270   - return newval;
271   - }
  198 + Validator operator!() const;
272 199  
273 200 private:
274   - void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger) {
275   -
276   - const std::function<std::string()> &dfunc1 = val1.desc_function_;
277   - const std::function<std::string()> &dfunc2 = val2.desc_function_;
278   -
279   - desc_function_ = [=]() {
280   - std::string f1 = dfunc1();
281   - std::string f2 = dfunc2();
282   - if((f1.empty()) || (f2.empty())) {
283   - return f1 + f2;
284   - }
285   - return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')';
286   - };
287   - }
288   -}; // namespace CLI
  201 + void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger);
  202 +};
289 203  
290 204 /// Class wrapping some of the accessors of Validator
291 205 class CustomValidator : public Validator {
... ... @@ -299,132 +213,37 @@ namespace detail {
299 213 /// CLI enumeration of different file types
300 214 enum class path_type { nonexistent, file, directory };
301 215  
302   -#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
303   -/// get the type of the path from a file name
304   -inline path_type check_path(const char *file) noexcept {
305   - std::error_code ec;
306   - auto stat = std::filesystem::status(file, ec);
307   - if(ec) {
308   - return path_type::nonexistent;
309   - }
310   - switch(stat.type()) {
311   - case std::filesystem::file_type::none:
312   - case std::filesystem::file_type::not_found:
313   - return path_type::nonexistent;
314   - case std::filesystem::file_type::directory:
315   - return path_type::directory;
316   - case std::filesystem::file_type::symlink:
317   - case std::filesystem::file_type::block:
318   - case std::filesystem::file_type::character:
319   - case std::filesystem::file_type::fifo:
320   - case std::filesystem::file_type::socket:
321   - case std::filesystem::file_type::regular:
322   - case std::filesystem::file_type::unknown:
323   - default:
324   - return path_type::file;
325   - }
326   -}
327   -#else
328 216 /// get the type of the path from a file name
329   -inline path_type check_path(const char *file) noexcept {
330   -#if defined(_MSC_VER)
331   - struct __stat64 buffer;
332   - if(_stat64(file, &buffer) == 0) {
333   - return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
334   - }
335   -#else
336   - struct stat buffer;
337   - if(stat(file, &buffer) == 0) {
338   - return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
339   - }
340   -#endif
341   - return path_type::nonexistent;
342   -}
343   -#endif
  217 +CLI11_INLINE path_type check_path(const char *file) noexcept;
  218 +
344 219 /// Check for an existing file (returns error message if check fails)
345 220 class ExistingFileValidator : public Validator {
346 221 public:
347   - ExistingFileValidator() : Validator("FILE") {
348   - func_ = [](std::string &filename) {
349   - auto path_result = check_path(filename.c_str());
350   - if(path_result == path_type::nonexistent) {
351   - return "File does not exist: " + filename;
352   - }
353   - if(path_result == path_type::directory) {
354   - return "File is actually a directory: " + filename;
355   - }
356   - return std::string();
357   - };
358   - }
  222 + ExistingFileValidator();
359 223 };
360 224  
361 225 /// Check for an existing directory (returns error message if check fails)
362 226 class ExistingDirectoryValidator : public Validator {
363 227 public:
364   - ExistingDirectoryValidator() : Validator("DIR") {
365   - func_ = [](std::string &filename) {
366   - auto path_result = check_path(filename.c_str());
367   - if(path_result == path_type::nonexistent) {
368   - return "Directory does not exist: " + filename;
369   - }
370   - if(path_result == path_type::file) {
371   - return "Directory is actually a file: " + filename;
372   - }
373   - return std::string();
374   - };
375   - }
  228 + ExistingDirectoryValidator();
376 229 };
377 230  
378 231 /// Check for an existing path
379 232 class ExistingPathValidator : public Validator {
380 233 public:
381   - ExistingPathValidator() : Validator("PATH(existing)") {
382   - func_ = [](std::string &filename) {
383   - auto path_result = check_path(filename.c_str());
384   - if(path_result == path_type::nonexistent) {
385   - return "Path does not exist: " + filename;
386   - }
387   - return std::string();
388   - };
389   - }
  234 + ExistingPathValidator();
390 235 };
391 236  
392 237 /// Check for an non-existing path
393 238 class NonexistentPathValidator : public Validator {
394 239 public:
395   - NonexistentPathValidator() : Validator("PATH(non-existing)") {
396   - func_ = [](std::string &filename) {
397   - auto path_result = check_path(filename.c_str());
398   - if(path_result != path_type::nonexistent) {
399   - return "Path already exists: " + filename;
400   - }
401   - return std::string();
402   - };
403   - }
  240 + NonexistentPathValidator();
404 241 };
405 242  
406 243 /// Validate the given string is a legal ipv4 address
407 244 class IPV4Validator : public Validator {
408 245 public:
409   - IPV4Validator() : Validator("IPV4") {
410   - func_ = [](std::string &ip_addr) {
411   - auto result = CLI::detail::split(ip_addr, '.');
412   - if(result.size() != 4) {
413   - return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')';
414   - }
415   - int num = 0;
416   - for(const auto &var : result) {
417   - bool retval = detail::lexical_cast(var, num);
418   - if(!retval) {
419   - return std::string("Failed parsing number (") + var + ')';
420   - }
421   - if(num < 0 || num > 255) {
422   - return std::string("Each IP number must be between 0 and 255 ") + var;
423   - }
424   - }
425   - return std::string();
426   - };
427   - }
  246 + IPV4Validator();
428 247 };
429 248  
430 249 } // namespace detail
... ... @@ -467,28 +286,7 @@ const TypeValidator&lt;double&gt; Number(&quot;NUMBER&quot;);
467 286 /// with the error return optionally disabled
468 287 class FileOnDefaultPath : public Validator {
469 288 public:
470   - explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true) : Validator("FILE") {
471   - func_ = [default_path, enableErrorReturn](std::string &filename) {
472   - auto path_result = detail::check_path(filename.c_str());
473   - if(path_result == detail::path_type::nonexistent) {
474   - std::string test_file_path = default_path;
475   - if(default_path.back() != '/' && default_path.back() != '\\') {
476   - // Add folder separator
477   - test_file_path += '/';
478   - }
479   - test_file_path.append(filename);
480   - path_result = detail::check_path(test_file_path.c_str());
481   - if(path_result == detail::path_type::file) {
482   - filename = test_file_path;
483   - } else {
484   - if(enableErrorReturn) {
485   - return "File does not exist: " + filename;
486   - }
487   - }
488   - }
489   - return std::string{};
490   - };
491   - }
  289 + explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true);
492 290 };
493 291  
494 292 /// Produce a range (factory). Min and max are inclusive.
... ... @@ -1082,43 +880,14 @@ class AsSizeValue : public AsNumberWithUnit {
1082 880 /// The first option is formally correct, but
1083 881 /// the second interpretation is more wide-spread
1084 882 /// (see https://en.wikipedia.org/wiki/Binary_prefix).
1085   - explicit AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) {
1086   - if(kb_is_1000) {
1087   - description("SIZE [b, kb(=1000b), kib(=1024b), ...]");
1088   - } else {
1089   - description("SIZE [b, kb(=1024b), ...]");
1090   - }
1091   - }
  883 + explicit AsSizeValue(bool kb_is_1000);
1092 884  
1093 885 private:
1094 886 /// Get <size unit, factor> mapping
1095   - static std::map<std::string, result_t> init_mapping(bool kb_is_1000) {
1096   - std::map<std::string, result_t> m;
1097   - result_t k_factor = kb_is_1000 ? 1000 : 1024;
1098   - result_t ki_factor = 1024;
1099   - result_t k = 1;
1100   - result_t ki = 1;
1101   - m["b"] = 1;
1102   - for(std::string p : {"k", "m", "g", "t", "p", "e"}) {
1103   - k *= k_factor;
1104   - ki *= ki_factor;
1105   - m[p] = k;
1106   - m[p + "b"] = k;
1107   - m[p + "i"] = ki;
1108   - m[p + "ib"] = ki;
1109   - }
1110   - return m;
1111   - }
  887 + static std::map<std::string, result_t> init_mapping(bool kb_is_1000);
1112 888  
1113 889 /// Cache calculated mapping
1114   - static std::map<std::string, result_t> get_mapping(bool kb_is_1000) {
1115   - if(kb_is_1000) {
1116   - static auto m = init_mapping(true);
1117   - return m;
1118   - }
1119   - static auto m = init_mapping(false);
1120   - return m;
1121   - }
  890 + static std::map<std::string, result_t> get_mapping(bool kb_is_1000);
1122 891 };
1123 892  
1124 893 namespace detail {
... ... @@ -1126,53 +895,14 @@ namespace detail {
1126 895 /// the string is assumed to contain a file name followed by other arguments
1127 896 /// the return value contains is a pair with the first argument containing the program name and the second
1128 897 /// everything else.
1129   -inline std::pair<std::string, std::string> split_program_name(std::string commandline) {
1130   - // try to determine the programName
1131   - std::pair<std::string, std::string> vals;
1132   - trim(commandline);
1133   - auto esp = commandline.find_first_of(' ', 1);
1134   - while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) {
1135   - esp = commandline.find_first_of(' ', esp + 1);
1136   - if(esp == std::string::npos) {
1137   - // if we have reached the end and haven't found a valid file just assume the first argument is the
1138   - // program name
1139   - if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') {
1140   - bool embeddedQuote = false;
1141   - auto keyChar = commandline[0];
1142   - auto end = commandline.find_first_of(keyChar, 1);
1143   - while((end != std::string::npos) && (commandline[end - 1] == '\\')) { // deal with escaped quotes
1144   - end = commandline.find_first_of(keyChar, end + 1);
1145   - embeddedQuote = true;
1146   - }
1147   - if(end != std::string::npos) {
1148   - vals.first = commandline.substr(1, end - 1);
1149   - esp = end + 1;
1150   - if(embeddedQuote) {
1151   - vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar));
1152   - }
1153   - } else {
1154   - esp = commandline.find_first_of(' ', 1);
1155   - }
1156   - } else {
1157   - esp = commandline.find_first_of(' ', 1);
1158   - }
1159   -
1160   - break;
1161   - }
1162   - }
1163   - if(vals.first.empty()) {
1164   - vals.first = commandline.substr(0, esp);
1165   - rtrim(vals.first);
1166   - }
1167   -
1168   - // strip the program name
1169   - vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{};
1170   - ltrim(vals.second);
1171   - return vals;
1172   -}
  898 +CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline);
1173 899  
1174 900 } // namespace detail
1175 901 /// @}
1176 902  
1177 903 // [CLI11:validators_hpp:end]
1178 904 } // namespace CLI
  905 +
  906 +#ifndef CLI11_COMPILE
  907 +#include "impl/Validators_inl.hpp"
  908 +#endif
... ...
include/CLI/impl/Validators_inl.hpp 0 → 100644
  1 +// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner
  2 +// under NSF AWARD 1414736 and by the respective contributors.
  3 +// All rights reserved.
  4 +//
  5 +// SPDX-License-Identifier: BSD-3-Clause
  6 +
  7 +#pragma once
  8 +
  9 +#include <CLI/Validators.hpp>
  10 +
  11 +#include <CLI/Macros.hpp>
  12 +#include <CLI/StringTools.hpp>
  13 +#include <CLI/TypeTools.hpp>
  14 +
  15 +// [CLI11:public_includes:set]
  16 +#include <map>
  17 +#include <string>
  18 +#include <utility>
  19 +// [CLI11:public_includes:end]
  20 +
  21 +namespace CLI {
  22 +// [CLI11:validators_inl_hpp:verbatim]
  23 +
  24 +CLI11_INLINE std::string Validator::operator()(std::string &str) const {
  25 + std::string retstring;
  26 + if(active_) {
  27 + if(non_modifying_) {
  28 + std::string value = str;
  29 + retstring = func_(value);
  30 + } else {
  31 + retstring = func_(str);
  32 + }
  33 + }
  34 + return retstring;
  35 +}
  36 +
  37 +CLI11_NODISCARD CLI11_INLINE Validator Validator::description(std::string validator_desc) const {
  38 + Validator newval(*this);
  39 + newval.desc_function_ = [validator_desc]() { return validator_desc; };
  40 + return newval;
  41 +}
  42 +
  43 +CLI11_INLINE Validator Validator::operator&(const Validator &other) const {
  44 + Validator newval;
  45 +
  46 + newval._merge_description(*this, other, " AND ");
  47 +
  48 + // Give references (will make a copy in lambda function)
  49 + const std::function<std::string(std::string & filename)> &f1 = func_;
  50 + const std::function<std::string(std::string & filename)> &f2 = other.func_;
  51 +
  52 + newval.func_ = [f1, f2](std::string &input) {
  53 + std::string s1 = f1(input);
  54 + std::string s2 = f2(input);
  55 + if(!s1.empty() && !s2.empty())
  56 + return std::string("(") + s1 + ") AND (" + s2 + ")";
  57 + return s1 + s2;
  58 + };
  59 +
  60 + newval.active_ = active_ && other.active_;
  61 + newval.application_index_ = application_index_;
  62 + return newval;
  63 +}
  64 +
  65 +CLI11_INLINE Validator Validator::operator|(const Validator &other) const {
  66 + Validator newval;
  67 +
  68 + newval._merge_description(*this, other, " OR ");
  69 +
  70 + // Give references (will make a copy in lambda function)
  71 + const std::function<std::string(std::string &)> &f1 = func_;
  72 + const std::function<std::string(std::string &)> &f2 = other.func_;
  73 +
  74 + newval.func_ = [f1, f2](std::string &input) {
  75 + std::string s1 = f1(input);
  76 + std::string s2 = f2(input);
  77 + if(s1.empty() || s2.empty())
  78 + return std::string();
  79 +
  80 + return std::string("(") + s1 + ") OR (" + s2 + ")";
  81 + };
  82 + newval.active_ = active_ && other.active_;
  83 + newval.application_index_ = application_index_;
  84 + return newval;
  85 +}
  86 +
  87 +CLI11_INLINE Validator Validator::operator!() const {
  88 + Validator newval;
  89 + const std::function<std::string()> &dfunc1 = desc_function_;
  90 + newval.desc_function_ = [dfunc1]() {
  91 + auto str = dfunc1();
  92 + return (!str.empty()) ? std::string("NOT ") + str : std::string{};
  93 + };
  94 + // Give references (will make a copy in lambda function)
  95 + const std::function<std::string(std::string & res)> &f1 = func_;
  96 +
  97 + newval.func_ = [f1, dfunc1](std::string &test) -> std::string {
  98 + std::string s1 = f1(test);
  99 + if(s1.empty()) {
  100 + return std::string("check ") + dfunc1() + " succeeded improperly";
  101 + }
  102 + return std::string{};
  103 + };
  104 + newval.active_ = active_;
  105 + newval.application_index_ = application_index_;
  106 + return newval;
  107 +}
  108 +
  109 +CLI11_INLINE void
  110 +Validator::_merge_description(const Validator &val1, const Validator &val2, const std::string &merger) {
  111 +
  112 + const std::function<std::string()> &dfunc1 = val1.desc_function_;
  113 + const std::function<std::string()> &dfunc2 = val2.desc_function_;
  114 +
  115 + desc_function_ = [=]() {
  116 + std::string f1 = dfunc1();
  117 + std::string f2 = dfunc2();
  118 + if((f1.empty()) || (f2.empty())) {
  119 + return f1 + f2;
  120 + }
  121 + return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')';
  122 + };
  123 +}
  124 +
  125 +namespace detail {
  126 +
  127 +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
  128 +CLI11_INLINE path_type check_path(const char *file) noexcept {
  129 + std::error_code ec;
  130 + auto stat = std::filesystem::status(file, ec);
  131 + if(ec) {
  132 + return path_type::nonexistent;
  133 + }
  134 + switch(stat.type()) {
  135 + case std::filesystem::file_type::none:
  136 + case std::filesystem::file_type::not_found:
  137 + return path_type::nonexistent;
  138 + case std::filesystem::file_type::directory:
  139 + return path_type::directory;
  140 + case std::filesystem::file_type::symlink:
  141 + case std::filesystem::file_type::block:
  142 + case std::filesystem::file_type::character:
  143 + case std::filesystem::file_type::fifo:
  144 + case std::filesystem::file_type::socket:
  145 + case std::filesystem::file_type::regular:
  146 + case std::filesystem::file_type::unknown:
  147 + default:
  148 + return path_type::file;
  149 + }
  150 +}
  151 +#else
  152 +CLI11_INLINE path_type check_path(const char *file) noexcept {
  153 +#if defined(_MSC_VER)
  154 + struct __stat64 buffer;
  155 + if(_stat64(file, &buffer) == 0) {
  156 + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
  157 + }
  158 +#else
  159 + struct stat buffer;
  160 + if(stat(file, &buffer) == 0) {
  161 + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
  162 + }
  163 +#endif
  164 + return path_type::nonexistent;
  165 +}
  166 +#endif
  167 +
  168 +CLI11_INLINE ExistingFileValidator::ExistingFileValidator() : Validator("FILE") {
  169 + func_ = [](std::string &filename) {
  170 + auto path_result = check_path(filename.c_str());
  171 + if(path_result == path_type::nonexistent) {
  172 + return "File does not exist: " + filename;
  173 + }
  174 + if(path_result == path_type::directory) {
  175 + return "File is actually a directory: " + filename;
  176 + }
  177 + return std::string();
  178 + };
  179 +}
  180 +
  181 +CLI11_INLINE ExistingDirectoryValidator::ExistingDirectoryValidator() : Validator("DIR") {
  182 + func_ = [](std::string &filename) {
  183 + auto path_result = check_path(filename.c_str());
  184 + if(path_result == path_type::nonexistent) {
  185 + return "Directory does not exist: " + filename;
  186 + }
  187 + if(path_result == path_type::file) {
  188 + return "Directory is actually a file: " + filename;
  189 + }
  190 + return std::string();
  191 + };
  192 +}
  193 +
  194 +CLI11_INLINE ExistingPathValidator::ExistingPathValidator() : Validator("PATH(existing)") {
  195 + func_ = [](std::string &filename) {
  196 + auto path_result = check_path(filename.c_str());
  197 + if(path_result == path_type::nonexistent) {
  198 + return "Path does not exist: " + filename;
  199 + }
  200 + return std::string();
  201 + };
  202 +}
  203 +
  204 +CLI11_INLINE NonexistentPathValidator::NonexistentPathValidator() : Validator("PATH(non-existing)") {
  205 + func_ = [](std::string &filename) {
  206 + auto path_result = check_path(filename.c_str());
  207 + if(path_result != path_type::nonexistent) {
  208 + return "Path already exists: " + filename;
  209 + }
  210 + return std::string();
  211 + };
  212 +}
  213 +
  214 +CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") {
  215 + func_ = [](std::string &ip_addr) {
  216 + auto result = CLI::detail::split(ip_addr, '.');
  217 + if(result.size() != 4) {
  218 + return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')';
  219 + }
  220 + int num = 0;
  221 + for(const auto &var : result) {
  222 + bool retval = detail::lexical_cast(var, num);
  223 + if(!retval) {
  224 + return std::string("Failed parsing number (") + var + ')';
  225 + }
  226 + if(num < 0 || num > 255) {
  227 + return std::string("Each IP number must be between 0 and 255 ") + var;
  228 + }
  229 + }
  230 + return std::string();
  231 + };
  232 +}
  233 +
  234 +} // namespace detail
  235 +
  236 +CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path, bool enableErrorReturn)
  237 + : Validator("FILE") {
  238 + func_ = [default_path, enableErrorReturn](std::string &filename) {
  239 + auto path_result = detail::check_path(filename.c_str());
  240 + if(path_result == detail::path_type::nonexistent) {
  241 + std::string test_file_path = default_path;
  242 + if(default_path.back() != '/' && default_path.back() != '\\') {
  243 + // Add folder separator
  244 + test_file_path += '/';
  245 + }
  246 + test_file_path.append(filename);
  247 + path_result = detail::check_path(test_file_path.c_str());
  248 + if(path_result == detail::path_type::file) {
  249 + filename = test_file_path;
  250 + } else {
  251 + if(enableErrorReturn) {
  252 + return "File does not exist: " + filename;
  253 + }
  254 + }
  255 + }
  256 + return std::string{};
  257 + };
  258 +}
  259 +
  260 +CLI11_INLINE AsSizeValue::AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) {
  261 + if(kb_is_1000) {
  262 + description("SIZE [b, kb(=1000b), kib(=1024b), ...]");
  263 + } else {
  264 + description("SIZE [b, kb(=1024b), ...]");
  265 + }
  266 +}
  267 +
  268 +CLI11_INLINE std::map<std::string, AsSizeValue::result_t> AsSizeValue::init_mapping(bool kb_is_1000) {
  269 + std::map<std::string, result_t> m;
  270 + result_t k_factor = kb_is_1000 ? 1000 : 1024;
  271 + result_t ki_factor = 1024;
  272 + result_t k = 1;
  273 + result_t ki = 1;
  274 + m["b"] = 1;
  275 + for(std::string p : {"k", "m", "g", "t", "p", "e"}) {
  276 + k *= k_factor;
  277 + ki *= ki_factor;
  278 + m[p] = k;
  279 + m[p + "b"] = k;
  280 + m[p + "i"] = ki;
  281 + m[p + "ib"] = ki;
  282 + }
  283 + return m;
  284 +}
  285 +
  286 +CLI11_INLINE std::map<std::string, AsSizeValue::result_t> AsSizeValue::get_mapping(bool kb_is_1000) {
  287 + if(kb_is_1000) {
  288 + static auto m = init_mapping(true);
  289 + return m;
  290 + }
  291 + static auto m = init_mapping(false);
  292 + return m;
  293 +}
  294 +
  295 +namespace detail {
  296 +
  297 +CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline) {
  298 + // try to determine the programName
  299 + std::pair<std::string, std::string> vals;
  300 + trim(commandline);
  301 + auto esp = commandline.find_first_of(' ', 1);
  302 + while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) {
  303 + esp = commandline.find_first_of(' ', esp + 1);
  304 + if(esp == std::string::npos) {
  305 + // if we have reached the end and haven't found a valid file just assume the first argument is the
  306 + // program name
  307 + if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') {
  308 + bool embeddedQuote = false;
  309 + auto keyChar = commandline[0];
  310 + auto end = commandline.find_first_of(keyChar, 1);
  311 + while((end != std::string::npos) && (commandline[end - 1] == '\\')) { // deal with escaped quotes
  312 + end = commandline.find_first_of(keyChar, end + 1);
  313 + embeddedQuote = true;
  314 + }
  315 + if(end != std::string::npos) {
  316 + vals.first = commandline.substr(1, end - 1);
  317 + esp = end + 1;
  318 + if(embeddedQuote) {
  319 + vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar));
  320 + }
  321 + } else {
  322 + esp = commandline.find_first_of(' ', 1);
  323 + }
  324 + } else {
  325 + esp = commandline.find_first_of(' ', 1);
  326 + }
  327 +
  328 + break;
  329 + }
  330 + }
  331 + if(vals.first.empty()) {
  332 + vals.first = commandline.substr(0, esp);
  333 + rtrim(vals.first);
  334 + }
  335 +
  336 + // strip the program name
  337 + vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{};
  338 + ltrim(vals.second);
  339 + return vals;
  340 +}
  341 +
  342 +} // namespace detail
  343 +/// @}
  344 +
  345 +// [CLI11:validators_inl_hpp:end]
  346 +} // namespace CLI
... ...
src/Validators.cpp 0 → 100644
  1 +// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner
  2 +// under NSF AWARD 1414736 and by the respective contributors.
  3 +// All rights reserved.
  4 +//
  5 +// SPDX-License-Identifier: BSD-3-Clause
  6 +
  7 +#include <CLI/impl/Validators_inl.hpp>
... ...