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 // This include is only needed for IDEs to discover symbols
0010 #include <CLI/StringTools.hpp>
0011 
0012 // [CLI11:public_includes:set]
0013 #include <string>
0014 #include <vector>
0015 // [CLI11:public_includes:end]
0016 
0017 namespace CLI {
0018 // [CLI11:string_tools_inl_hpp:verbatim]
0019 
0020 namespace detail {
0021 CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim) {
0022     std::vector<std::string> elems;
0023     // Check to see if empty string, give consistent result
0024     if(s.empty()) {
0025         elems.emplace_back();
0026     } else {
0027         std::stringstream ss;
0028         ss.str(s);
0029         std::string item;
0030         while(std::getline(ss, item, delim)) {
0031             elems.push_back(item);
0032         }
0033     }
0034     return elems;
0035 }
0036 
0037 CLI11_INLINE std::string &ltrim(std::string &str) {
0038     auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
0039     str.erase(str.begin(), it);
0040     return str;
0041 }
0042 
0043 CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter) {
0044     auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
0045     str.erase(str.begin(), it);
0046     return str;
0047 }
0048 
0049 CLI11_INLINE std::string &rtrim(std::string &str) {
0050     auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
0051     str.erase(it.base(), str.end());
0052     return str;
0053 }
0054 
0055 CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter) {
0056     auto it =
0057         std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
0058     str.erase(it.base(), str.end());
0059     return str;
0060 }
0061 
0062 CLI11_INLINE std::string &remove_quotes(std::string &str) {
0063     if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) {
0064         if(str.front() == str.back()) {
0065             str.pop_back();
0066             str.erase(str.begin(), str.begin() + 1);
0067         }
0068     }
0069     return str;
0070 }
0071 
0072 CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input) {
0073     std::string::size_type n = 0;
0074     while(n != std::string::npos && n < input.size()) {
0075         n = input.find('\n', n);
0076         if(n != std::string::npos) {
0077             input = input.substr(0, n + 1) + leader + input.substr(n + 1);
0078             n += leader.size();
0079         }
0080     }
0081     return input;
0082 }
0083 
0084 CLI11_INLINE std::ostream &
0085 format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
0086     name = "  " + name;
0087     out << std::setw(static_cast<int>(wid)) << std::left << name;
0088     if(!description.empty()) {
0089         if(name.length() >= wid)
0090             out << "\n" << std::setw(static_cast<int>(wid)) << "";
0091         for(const char c : description) {
0092             out.put(c);
0093             if(c == '\n') {
0094                 out << std::setw(static_cast<int>(wid)) << "";
0095             }
0096         }
0097     }
0098     out << "\n";
0099     return out;
0100 }
0101 
0102 CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
0103     if(!aliases.empty()) {
0104         out << std::setw(static_cast<int>(wid)) << "     aliases: ";
0105         bool front = true;
0106         for(const auto &alias : aliases) {
0107             if(!front) {
0108                 out << ", ";
0109             } else {
0110                 front = false;
0111             }
0112             out << detail::fix_newlines("              ", alias);
0113         }
0114         out << "\n";
0115     }
0116     return out;
0117 }
0118 
0119 CLI11_INLINE bool valid_name_string(const std::string &str) {
0120     if(str.empty() || !valid_first_char(str[0])) {
0121         return false;
0122     }
0123     auto e = str.end();
0124     for(auto c = str.begin() + 1; c != e; ++c)
0125         if(!valid_later_char(*c))
0126             return false;
0127     return true;
0128 }
0129 
0130 CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to) {
0131 
0132     std::size_t start_pos = 0;
0133 
0134     while((start_pos = str.find(from, start_pos)) != std::string::npos) {
0135         str.replace(start_pos, from.length(), to);
0136         start_pos += to.length();
0137     }
0138 
0139     return str;
0140 }
0141 
0142 CLI11_INLINE void remove_default_flag_values(std::string &flags) {
0143     auto loc = flags.find_first_of('{', 2);
0144     while(loc != std::string::npos) {
0145         auto finish = flags.find_first_of("},", loc + 1);
0146         if((finish != std::string::npos) && (flags[finish] == '}')) {
0147             flags.erase(flags.begin() + static_cast<std::ptrdiff_t>(loc),
0148                         flags.begin() + static_cast<std::ptrdiff_t>(finish) + 1);
0149         }
0150         loc = flags.find_first_of('{', loc + 1);
0151     }
0152     flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end());
0153 }
0154 
0155 CLI11_INLINE std::ptrdiff_t
0156 find_member(std::string name, const std::vector<std::string> names, bool ignore_case, bool ignore_underscore) {
0157     auto it = std::end(names);
0158     if(ignore_case) {
0159         if(ignore_underscore) {
0160             name = detail::to_lower(detail::remove_underscore(name));
0161             it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
0162                 return detail::to_lower(detail::remove_underscore(local_name)) == name;
0163             });
0164         } else {
0165             name = detail::to_lower(name);
0166             it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
0167                 return detail::to_lower(local_name) == name;
0168             });
0169         }
0170 
0171     } else if(ignore_underscore) {
0172         name = detail::remove_underscore(name);
0173         it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
0174             return detail::remove_underscore(local_name) == name;
0175         });
0176     } else {
0177         it = std::find(std::begin(names), std::end(names), name);
0178     }
0179 
0180     return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
0181 }
0182 
0183 CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter) {
0184 
0185     const std::string delims("\'\"`");
0186     auto find_ws = [delimiter](char ch) {
0187         return (delimiter == '\0') ? std::isspace<char>(ch, std::locale()) : (ch == delimiter);
0188     };
0189     trim(str);
0190 
0191     std::vector<std::string> output;
0192     bool embeddedQuote = false;
0193     char keyChar = ' ';
0194     while(!str.empty()) {
0195         if(delims.find_first_of(str[0]) != std::string::npos) {
0196             keyChar = str[0];
0197             auto end = str.find_first_of(keyChar, 1);
0198             while((end != std::string::npos) && (str[end - 1] == '\\')) {  // deal with escaped quotes
0199                 end = str.find_first_of(keyChar, end + 1);
0200                 embeddedQuote = true;
0201             }
0202             if(end != std::string::npos) {
0203                 output.push_back(str.substr(1, end - 1));
0204                 if(end + 2 < str.size()) {
0205                     str = str.substr(end + 2);
0206                 } else {
0207                     str.clear();
0208                 }
0209 
0210             } else {
0211                 output.push_back(str.substr(1));
0212                 str = "";
0213             }
0214         } else {
0215             auto it = std::find_if(std::begin(str), std::end(str), find_ws);
0216             if(it != std::end(str)) {
0217                 std::string value = std::string(str.begin(), it);
0218                 output.push_back(value);
0219                 str = std::string(it + 1, str.end());
0220             } else {
0221                 output.push_back(str);
0222                 str = "";
0223             }
0224         }
0225         // transform any embedded quotes into the regular character
0226         if(embeddedQuote) {
0227             output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));
0228             embeddedQuote = false;
0229         }
0230         trim(str);
0231     }
0232     return output;
0233 }
0234 
0235 CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset) {
0236     auto next = str[offset + 1];
0237     if((next == '\"') || (next == '\'') || (next == '`')) {
0238         auto astart = str.find_last_of("-/ \"\'`", offset - 1);
0239         if(astart != std::string::npos) {
0240             if(str[astart] == ((str[offset] == '=') ? '-' : '/'))
0241                 str[offset] = ' ';  // interpret this as a space so the split_up works properly
0242         }
0243     }
0244     return offset + 1;
0245 }
0246 
0247 CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) {
0248     if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {
0249         char quote = str.find('"') < str.find('\'') ? '\'' : '"';
0250         if(str.find(' ') != std::string::npos) {
0251             str.insert(0, 1, quote);
0252             str.append(1, quote);
0253         }
0254     }
0255     return str;
0256 }
0257 
0258 }  // namespace detail
0259 // [CLI11:string_tools_inl_hpp:end]
0260 }  // namespace CLI