Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:43

0001 // Copyright (c) 2017-2023, University of Cincinnati, developed by Henry Schreiner
0002 // under NSF AWARD 1414736 and by the respective contributors.
0003 // All rights reserved.
0004 //
0005 // SPDX-License-Identifier: BSD-3-Clause
0006 
0007 #pragma once
0008 
0009 #include <CLI/Validators.hpp>
0010 
0011 #include <CLI/Macros.hpp>
0012 #include <CLI/StringTools.hpp>
0013 #include <CLI/TypeTools.hpp>
0014 
0015 // [CLI11:public_includes:set]
0016 #include <map>
0017 #include <string>
0018 #include <utility>
0019 // [CLI11:public_includes:end]
0020 
0021 namespace CLI {
0022 // [CLI11:validators_inl_hpp:verbatim]
0023 
0024 CLI11_INLINE std::string Validator::operator()(std::string &str) const {
0025     std::string retstring;
0026     if(active_) {
0027         if(non_modifying_) {
0028             std::string value = str;
0029             retstring = func_(value);
0030         } else {
0031             retstring = func_(str);
0032         }
0033     }
0034     return retstring;
0035 }
0036 
0037 CLI11_NODISCARD CLI11_INLINE Validator Validator::description(std::string validator_desc) const {
0038     Validator newval(*this);
0039     newval.desc_function_ = [validator_desc]() { return validator_desc; };
0040     return newval;
0041 }
0042 
0043 CLI11_INLINE Validator Validator::operator&(const Validator &other) const {
0044     Validator newval;
0045 
0046     newval._merge_description(*this, other, " AND ");
0047 
0048     // Give references (will make a copy in lambda function)
0049     const std::function<std::string(std::string & filename)> &f1 = func_;
0050     const std::function<std::string(std::string & filename)> &f2 = other.func_;
0051 
0052     newval.func_ = [f1, f2](std::string &input) {
0053         std::string s1 = f1(input);
0054         std::string s2 = f2(input);
0055         if(!s1.empty() && !s2.empty())
0056             return std::string("(") + s1 + ") AND (" + s2 + ")";
0057         return s1 + s2;
0058     };
0059 
0060     newval.active_ = active_ && other.active_;
0061     newval.application_index_ = application_index_;
0062     return newval;
0063 }
0064 
0065 CLI11_INLINE Validator Validator::operator|(const Validator &other) const {
0066     Validator newval;
0067 
0068     newval._merge_description(*this, other, " OR ");
0069 
0070     // Give references (will make a copy in lambda function)
0071     const std::function<std::string(std::string &)> &f1 = func_;
0072     const std::function<std::string(std::string &)> &f2 = other.func_;
0073 
0074     newval.func_ = [f1, f2](std::string &input) {
0075         std::string s1 = f1(input);
0076         std::string s2 = f2(input);
0077         if(s1.empty() || s2.empty())
0078             return std::string();
0079 
0080         return std::string("(") + s1 + ") OR (" + s2 + ")";
0081     };
0082     newval.active_ = active_ && other.active_;
0083     newval.application_index_ = application_index_;
0084     return newval;
0085 }
0086 
0087 CLI11_INLINE Validator Validator::operator!() const {
0088     Validator newval;
0089     const std::function<std::string()> &dfunc1 = desc_function_;
0090     newval.desc_function_ = [dfunc1]() {
0091         auto str = dfunc1();
0092         return (!str.empty()) ? std::string("NOT ") + str : std::string{};
0093     };
0094     // Give references (will make a copy in lambda function)
0095     const std::function<std::string(std::string & res)> &f1 = func_;
0096 
0097     newval.func_ = [f1, dfunc1](std::string &test) -> std::string {
0098         std::string s1 = f1(test);
0099         if(s1.empty()) {
0100             return std::string("check ") + dfunc1() + " succeeded improperly";
0101         }
0102         return std::string{};
0103     };
0104     newval.active_ = active_;
0105     newval.application_index_ = application_index_;
0106     return newval;
0107 }
0108 
0109 CLI11_INLINE void
0110 Validator::_merge_description(const Validator &val1, const Validator &val2, const std::string &merger) {
0111 
0112     const std::function<std::string()> &dfunc1 = val1.desc_function_;
0113     const std::function<std::string()> &dfunc2 = val2.desc_function_;
0114 
0115     desc_function_ = [=]() {
0116         std::string f1 = dfunc1();
0117         std::string f2 = dfunc2();
0118         if((f1.empty()) || (f2.empty())) {
0119             return f1 + f2;
0120         }
0121         return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')';
0122     };
0123 }
0124 
0125 namespace detail {
0126 
0127 #if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
0128 CLI11_INLINE path_type check_path(const char *file) noexcept {
0129     std::error_code ec;
0130     auto stat = std::filesystem::status(file, ec);
0131     if(ec) {
0132         return path_type::nonexistent;
0133     }
0134     switch(stat.type()) {
0135     case std::filesystem::file_type::none:  // LCOV_EXCL_LINE
0136     case std::filesystem::file_type::not_found:
0137         return path_type::nonexistent;
0138     case std::filesystem::file_type::directory:
0139         return path_type::directory;
0140     case std::filesystem::file_type::symlink:
0141     case std::filesystem::file_type::block:
0142     case std::filesystem::file_type::character:
0143     case std::filesystem::file_type::fifo:
0144     case std::filesystem::file_type::socket:
0145     case std::filesystem::file_type::regular:
0146     case std::filesystem::file_type::unknown:
0147     default:
0148         return path_type::file;
0149     }
0150 }
0151 #else
0152 CLI11_INLINE path_type check_path(const char *file) noexcept {
0153 #if defined(_MSC_VER)
0154     struct __stat64 buffer;
0155     if(_stat64(file, &buffer) == 0) {
0156         return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
0157     }
0158 #else
0159     struct stat buffer;
0160     if(stat(file, &buffer) == 0) {
0161         return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file;
0162     }
0163 #endif
0164     return path_type::nonexistent;
0165 }
0166 #endif
0167 
0168 CLI11_INLINE ExistingFileValidator::ExistingFileValidator() : Validator("FILE") {
0169     func_ = [](std::string &filename) {
0170         auto path_result = check_path(filename.c_str());
0171         if(path_result == path_type::nonexistent) {
0172             return "File does not exist: " + filename;
0173         }
0174         if(path_result == path_type::directory) {
0175             return "File is actually a directory: " + filename;
0176         }
0177         return std::string();
0178     };
0179 }
0180 
0181 CLI11_INLINE ExistingDirectoryValidator::ExistingDirectoryValidator() : Validator("DIR") {
0182     func_ = [](std::string &filename) {
0183         auto path_result = check_path(filename.c_str());
0184         if(path_result == path_type::nonexistent) {
0185             return "Directory does not exist: " + filename;
0186         }
0187         if(path_result == path_type::file) {
0188             return "Directory is actually a file: " + filename;
0189         }
0190         return std::string();
0191     };
0192 }
0193 
0194 CLI11_INLINE ExistingPathValidator::ExistingPathValidator() : Validator("PATH(existing)") {
0195     func_ = [](std::string &filename) {
0196         auto path_result = check_path(filename.c_str());
0197         if(path_result == path_type::nonexistent) {
0198             return "Path does not exist: " + filename;
0199         }
0200         return std::string();
0201     };
0202 }
0203 
0204 CLI11_INLINE NonexistentPathValidator::NonexistentPathValidator() : Validator("PATH(non-existing)") {
0205     func_ = [](std::string &filename) {
0206         auto path_result = check_path(filename.c_str());
0207         if(path_result != path_type::nonexistent) {
0208             return "Path already exists: " + filename;
0209         }
0210         return std::string();
0211     };
0212 }
0213 
0214 CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") {
0215     func_ = [](std::string &ip_addr) {
0216         auto result = CLI::detail::split(ip_addr, '.');
0217         if(result.size() != 4) {
0218             return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')';
0219         }
0220         int num = 0;
0221         for(const auto &var : result) {
0222             using CLI::detail::lexical_cast;
0223             bool retval = lexical_cast(var, num);
0224             if(!retval) {
0225                 return std::string("Failed parsing number (") + var + ')';
0226             }
0227             if(num < 0 || num > 255) {
0228                 return std::string("Each IP number must be between 0 and 255 ") + var;
0229             }
0230         }
0231         return std::string();
0232     };
0233 }
0234 
0235 }  // namespace detail
0236 
0237 CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path, bool enableErrorReturn)
0238     : Validator("FILE") {
0239     func_ = [default_path, enableErrorReturn](std::string &filename) {
0240         auto path_result = detail::check_path(filename.c_str());
0241         if(path_result == detail::path_type::nonexistent) {
0242             std::string test_file_path = default_path;
0243             if(default_path.back() != '/' && default_path.back() != '\\') {
0244                 // Add folder separator
0245                 test_file_path += '/';
0246             }
0247             test_file_path.append(filename);
0248             path_result = detail::check_path(test_file_path.c_str());
0249             if(path_result == detail::path_type::file) {
0250                 filename = test_file_path;
0251             } else {
0252                 if(enableErrorReturn) {
0253                     return "File does not exist: " + filename;
0254                 }
0255             }
0256         }
0257         return std::string{};
0258     };
0259 }
0260 
0261 CLI11_INLINE AsSizeValue::AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) {
0262     if(kb_is_1000) {
0263         description("SIZE [b, kb(=1000b), kib(=1024b), ...]");
0264     } else {
0265         description("SIZE [b, kb(=1024b), ...]");
0266     }
0267 }
0268 
0269 CLI11_INLINE std::map<std::string, AsSizeValue::result_t> AsSizeValue::init_mapping(bool kb_is_1000) {
0270     std::map<std::string, result_t> m;
0271     result_t k_factor = kb_is_1000 ? 1000 : 1024;
0272     result_t ki_factor = 1024;
0273     result_t k = 1;
0274     result_t ki = 1;
0275     m["b"] = 1;
0276     for(std::string p : {"k", "m", "g", "t", "p", "e"}) {
0277         k *= k_factor;
0278         ki *= ki_factor;
0279         m[p] = k;
0280         m[p + "b"] = k;
0281         m[p + "i"] = ki;
0282         m[p + "ib"] = ki;
0283     }
0284     return m;
0285 }
0286 
0287 CLI11_INLINE std::map<std::string, AsSizeValue::result_t> AsSizeValue::get_mapping(bool kb_is_1000) {
0288     if(kb_is_1000) {
0289         static auto m = init_mapping(true);
0290         return m;
0291     }
0292     static auto m = init_mapping(false);
0293     return m;
0294 }
0295 
0296 namespace detail {
0297 
0298 CLI11_INLINE std::pair<std::string, std::string> split_program_name(std::string commandline) {
0299     // try to determine the programName
0300     std::pair<std::string, std::string> vals;
0301     trim(commandline);
0302     auto esp = commandline.find_first_of(' ', 1);
0303     while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) {
0304         esp = commandline.find_first_of(' ', esp + 1);
0305         if(esp == std::string::npos) {
0306             // if we have reached the end and haven't found a valid file just assume the first argument is the
0307             // program name
0308             if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') {
0309                 bool embeddedQuote = false;
0310                 auto keyChar = commandline[0];
0311                 auto end = commandline.find_first_of(keyChar, 1);
0312                 while((end != std::string::npos) && (commandline[end - 1] == '\\')) {  // deal with escaped quotes
0313                     end = commandline.find_first_of(keyChar, end + 1);
0314                     embeddedQuote = true;
0315                 }
0316                 if(end != std::string::npos) {
0317                     vals.first = commandline.substr(1, end - 1);
0318                     esp = end + 1;
0319                     if(embeddedQuote) {
0320                         vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar));
0321                     }
0322                 } else {
0323                     esp = commandline.find_first_of(' ', 1);
0324                 }
0325             } else {
0326                 esp = commandline.find_first_of(' ', 1);
0327             }
0328 
0329             break;
0330         }
0331     }
0332     if(vals.first.empty()) {
0333         vals.first = commandline.substr(0, esp);
0334         rtrim(vals.first);
0335     }
0336 
0337     // strip the program name
0338     vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{};
0339     ltrim(vals.second);
0340     return vals;
0341 }
0342 
0343 }  // namespace detail
0344 /// @}
0345 
0346 // [CLI11:validators_inl_hpp:end]
0347 }  // namespace CLI