feat update
All checks were successful
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Successful in 1m5s
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Successful in 1m4s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Successful in 1m13s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Successful in 1m26s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Successful in 1m26s
linux-mips64-gcc / linux-gcc-mips64el (push) Successful in 1m38s
linux-x64-gcc / linux-gcc (push) Successful in 1m39s
All checks were successful
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Successful in 1m5s
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Successful in 1m4s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Successful in 1m13s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Successful in 1m26s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Successful in 1m26s
linux-mips64-gcc / linux-gcc-mips64el (push) Successful in 1m38s
linux-x64-gcc / linux-gcc (push) Successful in 1m39s
This commit is contained in:
parent
cc74cbfda7
commit
6086d0778e
@ -50,7 +50,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* There are only two hard things in Computer Science: cache invalidation and
|
||||
@ -100,42 +99,35 @@
|
||||
*/
|
||||
namespace argagg {
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* This exception is thrown when a long option is parsed and is given an
|
||||
* argument using the "=" syntax but the option doesn't expect an argument.
|
||||
*/
|
||||
struct unexpected_argument_error
|
||||
: public std::runtime_error {
|
||||
struct unexpected_argument_error : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* This exception is thrown when an option is parsed unexpectedly such as when
|
||||
* an argument was expected for a previous option or if an option was found
|
||||
* that has not been defined.
|
||||
*/
|
||||
struct unexpected_option_error
|
||||
: public std::runtime_error {
|
||||
struct unexpected_option_error : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* This exception is thrown when an option requires an argument but is not
|
||||
* provided one. This can happen if another flag was found after the option or
|
||||
* if we simply reach the end of the command line arguments.
|
||||
*/
|
||||
struct option_lacks_argument_error
|
||||
: public std::runtime_error {
|
||||
struct option_lacks_argument_error : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* This exception is thrown when an option's flag is invalid. This can be the
|
||||
@ -143,12 +135,10 @@ struct option_lacks_argument_error
|
||||
* alpha-numeric characters after the hypens. See is_valid_flag_definition()
|
||||
* for more details.
|
||||
*/
|
||||
struct invalid_flag
|
||||
: public std::runtime_error {
|
||||
struct invalid_flag : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* The set of template instantiations that convert C-strings to other types for
|
||||
@ -165,8 +155,7 @@ namespace convert {
|
||||
template<typename T>
|
||||
T arg(const char *arg);
|
||||
|
||||
}
|
||||
|
||||
}// namespace convert
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@ -222,10 +211,8 @@ struct option_result {
|
||||
*/
|
||||
template<typename T>
|
||||
operator T() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Represents multiple option parse results for a single option. If treated as
|
||||
@ -299,10 +286,8 @@ struct option_results {
|
||||
*/
|
||||
template<typename T>
|
||||
operator T() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Represents all results of the parser including options and positional
|
||||
@ -377,10 +362,8 @@ struct parser_results {
|
||||
*/
|
||||
template<typename T>
|
||||
std::vector<T> all_as() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* An option definition which essentially represents what an option is.
|
||||
@ -425,10 +408,8 @@ struct definition {
|
||||
* Returns true if this option requires arguments.
|
||||
*/
|
||||
bool requires_arguments() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Checks whether or not a command line argument should be processed as an
|
||||
@ -436,27 +417,21 @@ struct definition {
|
||||
* allow for short flag groups (e.g. "-abc") and equal-assigned long flag
|
||||
* arguments (e.g. "--output=foo.txt").
|
||||
*/
|
||||
bool cmd_line_arg_is_option_flag(
|
||||
const char* s);
|
||||
|
||||
bool cmd_line_arg_is_option_flag(const char *s);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Checks whether a flag in an option definition is valid. I suggest reading
|
||||
* through the function source to understand what dictates a valid.
|
||||
*/
|
||||
bool is_valid_flag_definition(
|
||||
const char* s);
|
||||
|
||||
bool is_valid_flag_definition(const char *s);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Tests whether or not a valid flag is short. Assumes the provided cstring is
|
||||
* already a valid flag.
|
||||
*/
|
||||
bool flag_is_short(
|
||||
const char* s);
|
||||
|
||||
bool flag_is_short(const char *s);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@ -489,35 +464,30 @@ struct parser_map {
|
||||
* @brief
|
||||
* Returns true if the provided short flag exists in the map object.
|
||||
*/
|
||||
bool known_short_flag(
|
||||
const char flag) const;
|
||||
bool known_short_flag(const char flag) const;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* If the short flag exists in the map object then it is returned by this
|
||||
* method. If it doesn't then nullptr will be returned.
|
||||
*/
|
||||
const definition* get_definition_for_short_flag(
|
||||
const char flag) const;
|
||||
const definition *get_definition_for_short_flag(const char flag) const;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Returns true if the provided long flag exists in the map object.
|
||||
*/
|
||||
bool known_long_flag(
|
||||
const std::string& flag) const;
|
||||
bool known_long_flag(const std::string &flag) const;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* If the long flag exists in the map object then it is returned by this
|
||||
* method. If it doesn't then nullptr will be returned.
|
||||
*/
|
||||
const definition* get_definition_for_long_flag(
|
||||
const std::string& flag) const;
|
||||
|
||||
const definition *
|
||||
get_definition_for_long_flag(const std::string &flag) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Validates a collection (specifically an std::vector) of @ref definition
|
||||
@ -525,9 +495,7 @@ struct parser_map {
|
||||
* definition objects is not valid then an exception is thrown. Upon successful
|
||||
* validation a @ref parser_map object is returned.
|
||||
*/
|
||||
parser_map validate_definitions(
|
||||
const std::vector<definition>& definitions);
|
||||
|
||||
parser_map validate_definitions(const std::vector<definition> &definitions);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@ -561,10 +529,8 @@ struct parser {
|
||||
* which is typically frowned upon but is safe here.
|
||||
*/
|
||||
parser_results parse(int argc, char **argv) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* A convenience output stream that will accumulate what is streamed to it and
|
||||
@ -611,10 +577,8 @@ struct fmt_ostream : public std::ostringstream {
|
||||
* stored.
|
||||
*/
|
||||
~fmt_ostream();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Processes the provided string using the fmt util and returns the resulting
|
||||
@ -632,25 +596,21 @@ struct fmt_ostream : public std::ostringstream {
|
||||
*/
|
||||
std::string fmt_string(const std::string &s);
|
||||
|
||||
|
||||
}// namespace argagg
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Writes the option help to the given stream.
|
||||
*/
|
||||
std::ostream &operator<<(std::ostream &os, const argagg::parser &x);
|
||||
|
||||
|
||||
// ---- end of declarations, header-only implementations follow ----
|
||||
|
||||
|
||||
namespace argagg {
|
||||
|
||||
|
||||
template<typename T>
|
||||
T option_result::as() const
|
||||
T
|
||||
option_result::as() const
|
||||
{
|
||||
if (this->arg) {
|
||||
return convert::arg<T>(this->arg);
|
||||
@ -659,9 +619,9 @@ T option_result::as() const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T option_result::as(const T& t) const
|
||||
T
|
||||
option_result::as(const T &t) const
|
||||
{
|
||||
if (this->arg) {
|
||||
try {
|
||||
@ -679,44 +639,39 @@ T option_result::as(const T& t) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
option_result::operator T() const
|
||||
{
|
||||
return this->as<T>();
|
||||
}
|
||||
|
||||
|
||||
template <> inline
|
||||
option_result::operator bool () const
|
||||
template<>
|
||||
inline option_result::operator bool() const
|
||||
{
|
||||
return this->arg != nullptr;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
std::size_t option_results::count() const
|
||||
inline std::size_t
|
||||
option_results::count() const
|
||||
{
|
||||
return this->all.size();
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
option_result& option_results::operator [] (std::size_t index)
|
||||
inline option_result &
|
||||
option_results::operator[](std::size_t index)
|
||||
{
|
||||
return this->all[index];
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
const option_result& option_results::operator [] (std::size_t index) const
|
||||
inline const option_result &
|
||||
option_results::operator[](std::size_t index) const
|
||||
{
|
||||
return this->all[index];
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T option_results::as() const
|
||||
T
|
||||
option_results::as() const
|
||||
{
|
||||
if (this->all.size() == 0) {
|
||||
throw std::out_of_range("no option arguments to convert");
|
||||
@ -724,118 +679,97 @@ T option_results::as() const
|
||||
return this->all.back().as<T>();
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T option_results::as(const T& t) const
|
||||
T
|
||||
option_results::as(const T &t) const
|
||||
{
|
||||
if (this->all.size() == 0) {
|
||||
return t;
|
||||
}
|
||||
if (this->all.size() == 0) { return t; }
|
||||
return this->all.back().as<T>(t);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
option_results::operator T() const
|
||||
{
|
||||
return this->as<T>();
|
||||
}
|
||||
|
||||
|
||||
template <> inline
|
||||
option_results::operator bool () const
|
||||
template<>
|
||||
inline option_results::operator bool() const
|
||||
{
|
||||
return this->all.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool parser_results::has_option(const std::string& name) const
|
||||
inline bool
|
||||
parser_results::has_option(const std::string &name) const
|
||||
{
|
||||
const auto it = this->options.find(name);
|
||||
return (it != this->options.end()) && it->second.all.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
option_results& parser_results::operator [] (const std::string& name)
|
||||
inline option_results &
|
||||
parser_results::operator[](const std::string &name)
|
||||
{
|
||||
return this->options.at(name);
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
const option_results&
|
||||
inline const option_results &
|
||||
parser_results::operator[](const std::string &name) const
|
||||
{
|
||||
return this->options.at(name);
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
std::size_t parser_results::count() const
|
||||
inline std::size_t
|
||||
parser_results::count() const
|
||||
{
|
||||
return this->pos.size();
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
const char* parser_results::operator [] (std::size_t index) const
|
||||
inline const char *
|
||||
parser_results::operator[](std::size_t index) const
|
||||
{
|
||||
return this->pos[index];
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T parser_results::as(std::size_t i) const
|
||||
T
|
||||
parser_results::as(std::size_t i) const
|
||||
{
|
||||
return convert::arg<T>(this->pos[i]);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> parser_results::all_as() const
|
||||
std::vector<T>
|
||||
parser_results::all_as() const
|
||||
{
|
||||
std::vector<T> v(this->pos.size());
|
||||
std::transform(
|
||||
this->pos.begin(), this->pos.end(), v.begin(),
|
||||
[](const char* arg) {
|
||||
return convert::arg<T>(arg);
|
||||
});
|
||||
std::transform(this->pos.begin(), this->pos.end(), v.begin(),
|
||||
[](const char *arg) { return convert::arg<T>(arg); });
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool definition::wants_no_arguments() const
|
||||
inline bool
|
||||
definition::wants_no_arguments() const
|
||||
{
|
||||
return this->num_args == 0;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool definition::requires_arguments() const
|
||||
inline bool
|
||||
definition::requires_arguments() const
|
||||
{
|
||||
return this->num_args > 0;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool cmd_line_arg_is_option_flag(
|
||||
const char* s)
|
||||
inline bool
|
||||
cmd_line_arg_is_option_flag(const char *s)
|
||||
{
|
||||
auto len = std::strlen(s);
|
||||
|
||||
// The shortest possible flag has two characters: a hyphen and an
|
||||
// alpha-numeric character.
|
||||
if (len < 2) {
|
||||
return false;
|
||||
}
|
||||
if (len < 2) { return false; }
|
||||
|
||||
// All flags must start with a hyphen.
|
||||
if (s[0] != '-') {
|
||||
return false;
|
||||
}
|
||||
if (s[0] != '-') { return false; }
|
||||
|
||||
// Shift the name forward by a character to account for the initial hyphen.
|
||||
// This means if s was originally "-v" then name will be "v".
|
||||
@ -847,9 +781,7 @@ bool cmd_line_arg_is_option_flag(
|
||||
is_long = true;
|
||||
|
||||
// Just -- is not a valid flag.
|
||||
if (len == 2) {
|
||||
return false;
|
||||
}
|
||||
if (len == 2) { return false; }
|
||||
|
||||
// Shift the name forward to account for the extra hyphen. This means if s
|
||||
// was originally "--output" then name will be "output".
|
||||
@ -859,9 +791,7 @@ bool cmd_line_arg_is_option_flag(
|
||||
// The first character of the flag name must be alpha-numeric. This is to
|
||||
// prevent things like "---a" from being valid flags.
|
||||
len = std::strlen(name);
|
||||
if (!std::isalnum(name[0])) {
|
||||
return false;
|
||||
}
|
||||
if (!std::isalnum(name[0])) { return false; }
|
||||
|
||||
// At this point in is_valid_flag_definition() we would check if the short
|
||||
// flag has only one character. At command line specification you can group
|
||||
@ -899,23 +829,17 @@ bool cmd_line_arg_is_option_flag(
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool is_valid_flag_definition(
|
||||
const char* s)
|
||||
inline bool
|
||||
is_valid_flag_definition(const char *s)
|
||||
{
|
||||
auto len = std::strlen(s);
|
||||
|
||||
// The shortest possible flag has two characters: a hyphen and an
|
||||
// alpha-numeric character.
|
||||
if (len < 2) {
|
||||
return false;
|
||||
}
|
||||
if (len < 2) { return false; }
|
||||
|
||||
// All flags must start with a hyphen.
|
||||
if (s[0] != '-') {
|
||||
return false;
|
||||
}
|
||||
if (s[0] != '-') { return false; }
|
||||
|
||||
// Shift the name forward by a character to account for the initial hyphen.
|
||||
// This means if s was originally "-v" then name will be "v".
|
||||
@ -927,9 +851,7 @@ bool is_valid_flag_definition(
|
||||
is_long = true;
|
||||
|
||||
// Just -- is not a valid flag.
|
||||
if (len == 2) {
|
||||
return false;
|
||||
}
|
||||
if (len == 2) { return false; }
|
||||
|
||||
// Shift the name forward to account for the extra hyphen. This means if s
|
||||
// was originally "--output" then name will be "output".
|
||||
@ -939,14 +861,10 @@ bool is_valid_flag_definition(
|
||||
// The first character of the flag name must be alpha-numeric. This is to
|
||||
// prevent things like "---a" from being valid flags.
|
||||
len = std::strlen(name);
|
||||
if (!std::isalnum(name[0])) {
|
||||
return false;
|
||||
}
|
||||
if (!std::isalnum(name[0])) { return false; }
|
||||
|
||||
// If this is a short flag then it must only have one character.
|
||||
if (!is_long && len > 1) {
|
||||
return false;
|
||||
}
|
||||
if (!is_long && len > 1) { return false; }
|
||||
|
||||
// The rest of the characters must be alpha-numeric, but long flags are
|
||||
// allowed to have hyphens too.
|
||||
@ -955,55 +873,41 @@ bool is_valid_flag_definition(
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool flag_is_short(
|
||||
const char* s)
|
||||
inline bool
|
||||
flag_is_short(const char *s)
|
||||
{
|
||||
return s[0] == '-' && std::isalnum(s[1]);
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool parser_map::known_short_flag(
|
||||
const char flag) const
|
||||
inline bool
|
||||
parser_map::known_short_flag(const char flag) const
|
||||
{
|
||||
return this->short_map[flag] != nullptr;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
const definition* parser_map::get_definition_for_short_flag(
|
||||
const char flag) const
|
||||
inline const definition *
|
||||
parser_map::get_definition_for_short_flag(const char flag) const
|
||||
{
|
||||
return this->short_map[flag];
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool parser_map::known_long_flag(
|
||||
const std::string& flag) const
|
||||
inline bool
|
||||
parser_map::known_long_flag(const std::string &flag) const
|
||||
{
|
||||
const auto existing_long_flag = this->long_map.find(flag);
|
||||
return existing_long_flag != long_map.end();
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
const definition* parser_map::get_definition_for_long_flag(
|
||||
const std::string& flag) const
|
||||
inline const definition *
|
||||
parser_map::get_definition_for_long_flag(const std::string &flag) const
|
||||
{
|
||||
const auto existing_long_flag = this->long_map.find(flag);
|
||||
if (existing_long_flag == long_map.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (existing_long_flag == long_map.end()) { return nullptr; }
|
||||
return existing_long_flag->second;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
parser_map validate_definitions(
|
||||
const std::vector<definition>& definitions)
|
||||
inline parser_map
|
||||
validate_definitions(const std::vector<definition> &definitions)
|
||||
{
|
||||
std::unordered_map<std::string, const definition *> long_map;
|
||||
parser_map map{{{nullptr}}, std::move(long_map)};
|
||||
@ -1020,15 +924,17 @@ parser_map validate_definitions(
|
||||
|
||||
if (!is_valid_flag_definition(flag.data())) {
|
||||
std::ostringstream msg;
|
||||
msg << "flag \"" << flag << "\" specified for option \"" << defn.name
|
||||
<< "\" is invalid";
|
||||
msg << "flag \"" << flag << "\" specified for option \""
|
||||
<< defn.name << "\" is invalid";
|
||||
throw invalid_flag(msg.str());
|
||||
}
|
||||
|
||||
if (flag_is_short(flag.data())) {
|
||||
const int short_flag_letter = flag[1];
|
||||
const auto existing_short_flag = map.short_map[short_flag_letter];
|
||||
bool short_flag_already_exists = (existing_short_flag != nullptr);
|
||||
const auto existing_short_flag =
|
||||
map.short_map[short_flag_letter];
|
||||
bool short_flag_already_exists =
|
||||
(existing_short_flag != nullptr);
|
||||
if (short_flag_already_exists) {
|
||||
std::ostringstream msg;
|
||||
msg << "duplicate short flag \"" << flag
|
||||
@ -1042,7 +948,8 @@ parser_map validate_definitions(
|
||||
|
||||
// If we're here then this is a valid, long-style flag.
|
||||
if (map.known_long_flag(flag)) {
|
||||
const auto existing_long_flag = map.get_definition_for_long_flag(flag);
|
||||
const auto existing_long_flag =
|
||||
map.get_definition_for_long_flag(flag);
|
||||
std::ostringstream msg;
|
||||
msg << "duplicate long flag \"" << flag
|
||||
<< "\" found, specified by both option \"" << defn.name
|
||||
@ -1056,9 +963,8 @@ parser_map validate_definitions(
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
parser_results parser::parse(int argc, const char** argv) const
|
||||
inline parser_results
|
||||
parser::parse(int argc, const char **argv) const
|
||||
{
|
||||
// Inspect each definition to see if its valid. You may wonder "why don't
|
||||
// you do this validation on construction?" I had thought about it but
|
||||
@ -1084,8 +990,7 @@ parser_results parser::parse(int argc, const char** argv) const
|
||||
// Add an empty option result for each definition.
|
||||
for (const auto &defn : this->definitions) {
|
||||
option_results opt_results{{}};
|
||||
results.options.insert(
|
||||
std::make_pair(defn.name, opt_results));
|
||||
results.options.insert(std::make_pair(defn.name, opt_results));
|
||||
}
|
||||
|
||||
// Don't start off ignoring flags. We only ignore flags after a -- shows up
|
||||
@ -1111,11 +1016,9 @@ parser_results parser::parse(int argc, const char** argv) const
|
||||
// Some behavior to note: if the previous option is expecting an argument
|
||||
// then the next entry will be treated as a positional argument even if
|
||||
// it looks like a flag.
|
||||
bool treat_as_positional_argument = (
|
||||
ignore_flags
|
||||
|| num_option_args_to_consume > 0
|
||||
|| !cmd_line_arg_is_option_flag(arg_i_cstr)
|
||||
);
|
||||
bool treat_as_positional_argument =
|
||||
(ignore_flags || num_option_args_to_consume > 0
|
||||
|| !cmd_line_arg_is_option_flag(arg_i_cstr));
|
||||
if (treat_as_positional_argument) {
|
||||
|
||||
// If last option is expecting some specific positive number of
|
||||
@ -1195,7 +1098,8 @@ parser_results parser::parse(int argc, const char** argv) const
|
||||
opt_results.all.push_back(std::move(opt_result));
|
||||
|
||||
if (defn->requires_arguments()) {
|
||||
bool there_is_an_equal_delimited_arg = (long_flag_arg != nullptr);
|
||||
bool there_is_an_equal_delimited_arg =
|
||||
(long_flag_arg != nullptr);
|
||||
if (there_is_an_equal_delimited_arg) {
|
||||
// long_flag_arg would be "=foo" in the "--output=foo" case so we
|
||||
// increment by 1 to get rid of the equal sign.
|
||||
@ -1223,8 +1127,9 @@ parser_results parser::parse(int argc, const char** argv) const
|
||||
|
||||
if (!std::isalnum(short_flag)) {
|
||||
std::ostringstream msg;
|
||||
msg << "found non-alphanumeric character '" << arg_i_cstr[sf_idx]
|
||||
<< "' in flag group '" << arg_i_cstr << "'";
|
||||
msg << "found non-alphanumeric character '"
|
||||
<< arg_i_cstr[sf_idx] << "' in flag group '" << arg_i_cstr
|
||||
<< "'";
|
||||
throw std::domain_error(msg.str());
|
||||
}
|
||||
|
||||
@ -1286,25 +1191,23 @@ parser_results parser::parse(int argc, const char** argv) const
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
parser_results parser::parse(int argc, char** argv) const
|
||||
inline parser_results
|
||||
parser::parse(int argc, char **argv) const
|
||||
{
|
||||
return parse(argc, const_cast<const char **>(argv));
|
||||
}
|
||||
|
||||
|
||||
namespace convert {
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Templated function for conversion to T using the @ref std::strtol()
|
||||
* function. This is used for anything long length or shorter (long, int,
|
||||
* short, char).
|
||||
*/
|
||||
template <typename T> inline
|
||||
T long_(const char* arg)
|
||||
template<typename T>
|
||||
inline T
|
||||
long_(const char *arg)
|
||||
{
|
||||
char *endptr = nullptr;
|
||||
errno = 0;
|
||||
@ -1320,15 +1223,15 @@ namespace convert {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Templated function for conversion to T using the @ref std::strtoll()
|
||||
* function. This is used for anything long long length or shorter (long
|
||||
* long).
|
||||
*/
|
||||
template <typename T> inline
|
||||
T long_long_(const char* arg)
|
||||
template<typename T>
|
||||
inline T
|
||||
long_long_(const char *arg)
|
||||
{
|
||||
char *endptr = nullptr;
|
||||
errno = 0;
|
||||
@ -1344,10 +1247,9 @@ namespace convert {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#define DEFINE_CONVERSION_FROM_LONG_(TYPE) \
|
||||
template <> inline \
|
||||
TYPE arg(const char* arg) \
|
||||
template<> \
|
||||
inline TYPE arg(const char *arg) \
|
||||
{ \
|
||||
return long_<TYPE>(arg); \
|
||||
}
|
||||
@ -1364,10 +1266,9 @@ namespace convert {
|
||||
|
||||
#undef DEFINE_CONVERSION_FROM_LONG_
|
||||
|
||||
|
||||
#define DEFINE_CONVERSION_FROM_LONG_LONG_(TYPE) \
|
||||
template <> inline \
|
||||
TYPE arg(const char* arg) \
|
||||
template<> \
|
||||
inline TYPE arg(const char *arg) \
|
||||
{ \
|
||||
return long_long_<TYPE>(arg); \
|
||||
}
|
||||
@ -1377,16 +1278,16 @@ namespace convert {
|
||||
|
||||
#undef DEFINE_CONVERSION_FROM_LONG_LONG_
|
||||
|
||||
|
||||
template <> inline
|
||||
bool arg(const char* arg)
|
||||
template<>
|
||||
inline bool
|
||||
arg(const char *arg)
|
||||
{
|
||||
return argagg::convert::arg<int>(arg) != 0;
|
||||
}
|
||||
|
||||
|
||||
template <> inline
|
||||
float arg(const char* arg)
|
||||
template<>
|
||||
inline float
|
||||
arg(const char *arg)
|
||||
{
|
||||
char *endptr = nullptr;
|
||||
errno = 0;
|
||||
@ -1402,9 +1303,9 @@ namespace convert {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <> inline
|
||||
double arg(const char* arg)
|
||||
template<>
|
||||
inline double
|
||||
arg(const char *arg)
|
||||
{
|
||||
char *endptr = nullptr;
|
||||
errno = 0;
|
||||
@ -1420,42 +1321,33 @@ namespace convert {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <> inline
|
||||
const char* arg(const char* arg)
|
||||
template<>
|
||||
inline const char *
|
||||
arg(const char *arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
template <> inline
|
||||
std::string arg(const char* arg)
|
||||
template<>
|
||||
inline std::string
|
||||
arg(const char *arg)
|
||||
{
|
||||
return std::string(arg);
|
||||
}
|
||||
|
||||
}
|
||||
}// namespace convert
|
||||
|
||||
inline fmt_ostream::fmt_ostream(std::ostream &output)
|
||||
: std::ostringstream(),
|
||||
output(output)
|
||||
{}
|
||||
|
||||
inline
|
||||
fmt_ostream::fmt_ostream(std::ostream& output)
|
||||
: std::ostringstream(), output(output)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
fmt_ostream::~fmt_ostream()
|
||||
{
|
||||
output << fmt_string(this->str());
|
||||
}
|
||||
|
||||
inline fmt_ostream::~fmt_ostream() { output << fmt_string(this->str()); }
|
||||
|
||||
#ifdef __unix__
|
||||
|
||||
|
||||
inline
|
||||
std::string fmt_string(const std::string& s)
|
||||
inline std::string
|
||||
fmt_string(const std::string &s)
|
||||
{
|
||||
constexpr int read_end = 0;
|
||||
constexpr int write_end = 1;
|
||||
@ -1465,12 +1357,8 @@ std::string fmt_string(const std::string& s)
|
||||
|
||||
int read_pipe[2];
|
||||
int write_pipe[2];
|
||||
if (pipe(read_pipe) == -1) {
|
||||
return s;
|
||||
}
|
||||
if (pipe(write_pipe) == -1) {
|
||||
return s;
|
||||
}
|
||||
if (pipe(read_pipe) == -1) { return s; }
|
||||
if (pipe(write_pipe) == -1) { return s; }
|
||||
|
||||
auto parent_pid = fork();
|
||||
bool is_fmt_proc = (parent_pid == 0);
|
||||
@ -1489,20 +1377,16 @@ std::string fmt_string(const std::string& s)
|
||||
close(read_pipe[write_end]);
|
||||
auto fmt_write_fd = write_pipe[write_end];
|
||||
auto write_result = write(fmt_write_fd, s.c_str(), s.length());
|
||||
if (write_result != static_cast<ssize_t>(s.length())) {
|
||||
return s;
|
||||
}
|
||||
if (write_result != static_cast<ssize_t>(s.length())) { return s; }
|
||||
close(fmt_write_fd);
|
||||
|
||||
auto fmt_read_fd = read_pipe[read_end];
|
||||
std::ostringstream os;
|
||||
char buf[64];
|
||||
while (true) {
|
||||
auto read_count = read(
|
||||
fmt_read_fd, reinterpret_cast<void*>(buf), sizeof(buf));
|
||||
if (read_count <= 0) {
|
||||
break;
|
||||
}
|
||||
auto read_count =
|
||||
read(fmt_read_fd, reinterpret_cast<void *>(buf), sizeof(buf));
|
||||
if (read_count <= 0) { break; }
|
||||
os.write(buf, static_cast<std::streamsize>(read_count));
|
||||
}
|
||||
close(fmt_read_fd);
|
||||
@ -1510,33 +1394,42 @@ std::string fmt_string(const std::string& s)
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
#else// #ifdef __unix__
|
||||
|
||||
|
||||
inline
|
||||
std::string fmt_string(const std::string& s)
|
||||
inline std::string
|
||||
fmt_string(const std::string &s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#endif// #ifdef __unix__
|
||||
|
||||
|
||||
}// namespace argagg
|
||||
|
||||
//
|
||||
namespace ulib {
|
||||
using parser = argagg::parser;
|
||||
using parser_results = argagg::parser_results;
|
||||
using option_results = argagg::option_results;
|
||||
using option_result = argagg::option_result;
|
||||
using definition = argagg::definition;
|
||||
using fmt_ostream = argagg::fmt_ostream;
|
||||
|
||||
inline
|
||||
std::ostream& operator << (std::ostream& os, const argagg::parser& x)
|
||||
inline std::string
|
||||
fmt_string(const std::string &s)
|
||||
{
|
||||
return argagg::fmt_string(s);
|
||||
};
|
||||
}// namespace ulib
|
||||
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream &os, const argagg::parser &x)
|
||||
{
|
||||
for (auto &definition : x.definitions) {
|
||||
os << " ";
|
||||
for (auto &flag : definition.flags) {
|
||||
os << flag;
|
||||
if (flag != definition.flags.back()) {
|
||||
os << ", ";
|
||||
}
|
||||
if (flag != definition.flags.back()) { os << ", "; }
|
||||
}
|
||||
os << std::endl;
|
||||
os << " " << definition.help << std::endl;
|
||||
@ -1544,5 +1437,4 @@ std::ostream& operator << (std::ostream& os, const argagg::parser& x)
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
#endif// ARGAGG_ARGAGG_ARGAGG_HPP
|
||||
|
Loading…
x
Reference in New Issue
Block a user