// Copyright (c) 2017-2022, University of Cincinnati, developed by Henry Schreiner // under NSF AWARD 1414736 and by the respective contributors. // All rights reserved. // // SPDX-License-Identifier: BSD-3-Clause #pragma once // [CLI11:public_includes:set] #include #include #include #include // [CLI11:public_includes:end] #include "Error.hpp" #include "StringTools.hpp" namespace CLI { // [CLI11:split_hpp:verbatim] namespace detail { // Returns false if not a short option. Otherwise, sets opt name and rest and returns true inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { name = current.substr(1, 1); rest = current.substr(2); return true; } return false; } // Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) { auto loc = current.find_first_of('='); if(loc != std::string::npos) { name = current.substr(2, loc - 2); value = current.substr(loc + 1); } else { name = current.substr(2); value = ""; } return true; } return false; } // Returns false if not a windows style option. Otherwise, sets opt name and value and returns true inline bool split_windows_style(const std::string ¤t, std::string &name, std::string &value) { if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) { auto loc = current.find_first_of(':'); if(loc != std::string::npos) { name = current.substr(1, loc - 1); value = current.substr(loc + 1); } else { name = current.substr(1); value = ""; } return true; } return false; } // Splits a string into multiple long and short names inline std::vector split_names(std::string current) { std::vector output; std::size_t val; while((val = current.find(",")) != std::string::npos) { output.push_back(trim_copy(current.substr(0, val))); current = current.substr(val + 1); } output.push_back(trim_copy(current)); return output; } /// extract default flag values either {def} or starting with a ! inline std::vector> get_default_flag_values(const std::string &str) { std::vector flags = split_names(str); flags.erase(std::remove_if(flags.begin(), flags.end(), [](const std::string &name) { return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) && (name.back() == '}')) || (name[0] == '!')))); }), flags.end()); std::vector> output; output.reserve(flags.size()); for(auto &flag : flags) { auto def_start = flag.find_first_of('{'); std::string defval = "false"; if((def_start != std::string::npos) && (flag.back() == '}')) { defval = flag.substr(def_start + 1); defval.pop_back(); flag.erase(def_start, std::string::npos); } flag.erase(0, flag.find_first_not_of("-!")); output.emplace_back(flag, defval); } return output; } /// Get a vector of short names, one of long names, and a single name inline std::tuple, std::vector, std::string> get_names(const std::vector &input) { std::vector short_names; std::vector long_names; std::string pos_name; for(std::string name : input) { if(name.length() == 0) { continue; } if(name.length() > 1 && name[0] == '-' && name[1] != '-') { if(name.length() == 2 && valid_first_char(name[1])) short_names.emplace_back(1, name[1]); else throw BadNameString::OneCharName(name); } else if(name.length() > 2 && name.substr(0, 2) == "--") { name = name.substr(2); if(valid_name_string(name)) long_names.push_back(name); else throw BadNameString::BadLongName(name); } else if(name == "-" || name == "--") { throw BadNameString::DashesOnly(name); } else { if(pos_name.length() > 0) throw BadNameString::MultiPositionalNames(name); pos_name = name; } } return std::tuple, std::vector, std::string>( short_names, long_names, pos_name); } } // namespace detail // [CLI11:split_hpp:end] } // namespace CLI