Back to home page

EIC code displayed by LXR

 
 

    


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

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 // [CLI11:public_includes:set]
0010 #include <algorithm>
0011 #include <iomanip>
0012 #include <locale>
0013 #include <sstream>
0014 #include <stdexcept>
0015 #include <string>
0016 #include <type_traits>
0017 #include <vector>
0018 // [CLI11:public_includes:end]
0019 
0020 #include "Macros.hpp"
0021 
0022 namespace CLI {
0023 
0024 // [CLI11:string_tools_hpp:verbatim]
0025 
0026 /// Include the items in this namespace to get free conversion of enums to/from streams.
0027 /// (This is available inside CLI as well, so CLI11 will use this without a using statement).
0028 namespace enums {
0029 
0030 /// output streaming for enumerations
0031 template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
0032 std::ostream &operator<<(std::ostream &in, const T &item) {
0033     // make sure this is out of the detail namespace otherwise it won't be found when needed
0034     return in << static_cast<typename std::underlying_type<T>::type>(item);
0035 }
0036 
0037 }  // namespace enums
0038 
0039 /// Export to CLI namespace
0040 using enums::operator<<;
0041 
0042 namespace detail {
0043 /// a constant defining an expected max vector size defined to be a big number that could be multiplied by 4 and not
0044 /// produce overflow for some expected uses
0045 constexpr int expected_max_vector_size{1 << 29};
0046 // Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
0047 /// Split a string by a delim
0048 CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim);
0049 
0050 /// Simple function to join a string
0051 template <typename T> std::string join(const T &v, std::string delim = ",") {
0052     std::ostringstream s;
0053     auto beg = std::begin(v);
0054     auto end = std::end(v);
0055     if(beg != end)
0056         s << *beg++;
0057     while(beg != end) {
0058         s << delim << *beg++;
0059     }
0060     return s.str();
0061 }
0062 
0063 /// Simple function to join a string from processed elements
0064 template <typename T,
0065           typename Callable,
0066           typename = typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
0067 std::string join(const T &v, Callable func, std::string delim = ",") {
0068     std::ostringstream s;
0069     auto beg = std::begin(v);
0070     auto end = std::end(v);
0071     auto loc = s.tellp();
0072     while(beg != end) {
0073         auto nloc = s.tellp();
0074         if(nloc > loc) {
0075             s << delim;
0076             loc = nloc;
0077         }
0078         s << func(*beg++);
0079     }
0080     return s.str();
0081 }
0082 
0083 /// Join a string in reverse order
0084 template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
0085     std::ostringstream s;
0086     for(std::size_t start = 0; start < v.size(); start++) {
0087         if(start > 0)
0088             s << delim;
0089         s << v[v.size() - start - 1];
0090     }
0091     return s.str();
0092 }
0093 
0094 // Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
0095 
0096 /// Trim whitespace from left of string
0097 CLI11_INLINE std::string &ltrim(std::string &str);
0098 
0099 /// Trim anything from left of string
0100 CLI11_INLINE std::string &ltrim(std::string &str, const std::string &filter);
0101 
0102 /// Trim whitespace from right of string
0103 CLI11_INLINE std::string &rtrim(std::string &str);
0104 
0105 /// Trim anything from right of string
0106 CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter);
0107 
0108 /// Trim whitespace from string
0109 inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
0110 
0111 /// Trim anything from string
0112 inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
0113 
0114 /// Make a copy of the string and then trim it
0115 inline std::string trim_copy(const std::string &str) {
0116     std::string s = str;
0117     return trim(s);
0118 }
0119 
0120 /// remove quotes at the front and back of a string either '"' or '\''
0121 CLI11_INLINE std::string &remove_quotes(std::string &str);
0122 
0123 /// Add a leader to the beginning of all new lines (nothing is added
0124 /// at the start of the first line). `"; "` would be for ini files
0125 ///
0126 /// Can't use Regex, or this would be a subs.
0127 CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input);
0128 
0129 /// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered)
0130 inline std::string trim_copy(const std::string &str, const std::string &filter) {
0131     std::string s = str;
0132     return trim(s, filter);
0133 }
0134 /// Print a two part "help" string
0135 CLI11_INLINE std::ostream &
0136 format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid);
0137 
0138 /// Print subcommand aliases
0139 CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid);
0140 
0141 /// Verify the first character of an option
0142 /// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with
0143 template <typename T> bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); }
0144 
0145 /// Verify following characters of an option
0146 template <typename T> bool valid_later_char(T c) {
0147     // = and : are value separators, { has special meaning for option defaults,
0148     // and \n would just be annoying to deal with in many places allowing space here has too much potential for
0149     // inadvertent entry errors and bugs
0150     return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n');
0151 }
0152 
0153 /// Verify an option/subcommand name
0154 CLI11_INLINE bool valid_name_string(const std::string &str);
0155 
0156 /// Verify an app name
0157 inline bool valid_alias_name_string(const std::string &str) {
0158     static const std::string badChars(std::string("\n") + '\0');
0159     return (str.find_first_of(badChars) == std::string::npos);
0160 }
0161 
0162 /// check if a string is a container segment separator (empty or "%%")
0163 inline bool is_separator(const std::string &str) {
0164     static const std::string sep("%%");
0165     return (str.empty() || str == sep);
0166 }
0167 
0168 /// Verify that str consists of letters only
0169 inline bool isalpha(const std::string &str) {
0170     return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); });
0171 }
0172 
0173 /// Return a lower case version of a string
0174 inline std::string to_lower(std::string str) {
0175     std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
0176         return std::tolower(x, std::locale());
0177     });
0178     return str;
0179 }
0180 
0181 /// remove underscores from a string
0182 inline std::string remove_underscore(std::string str) {
0183     str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str));
0184     return str;
0185 }
0186 
0187 /// Find and replace a substring with another substring
0188 CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to);
0189 
0190 /// check if the flag definitions has possible false flags
0191 inline bool has_default_flag_values(const std::string &flags) {
0192     return (flags.find_first_of("{!") != std::string::npos);
0193 }
0194 
0195 CLI11_INLINE void remove_default_flag_values(std::string &flags);
0196 
0197 /// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores
0198 CLI11_INLINE std::ptrdiff_t find_member(std::string name,
0199                                         const std::vector<std::string> names,
0200                                         bool ignore_case = false,
0201                                         bool ignore_underscore = false);
0202 
0203 /// Find a trigger string and call a modify callable function that takes the current string and starting position of the
0204 /// trigger and returns the position in the string to search for the next trigger string
0205 template <typename Callable> inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
0206     std::size_t start_pos = 0;
0207     while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
0208         start_pos = modify(str, start_pos);
0209     }
0210     return str;
0211 }
0212 
0213 /// Split a string '"one two" "three"' into 'one two', 'three'
0214 /// Quote characters can be ` ' or "
0215 CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter = '\0');
0216 
0217 /// This function detects an equal or colon followed by an escaped quote after an argument
0218 /// then modifies the string to replace the equality with a space.  This is needed
0219 /// to allow the split up function to work properly and is intended to be used with the find_and_modify function
0220 /// the return value is the offset+1 which is required by the find_and_modify function.
0221 CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset);
0222 
0223 /// Add quotes if the string contains spaces
0224 CLI11_INLINE std::string &add_quotes_if_needed(std::string &str);
0225 
0226 }  // namespace detail
0227 
0228 // [CLI11:string_tools_hpp:end]
0229 
0230 }  // namespace CLI
0231 
0232 #ifndef CLI11_COMPILE
0233 #include "impl/StringTools_inl.hpp"
0234 #endif