Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:11:14

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