OpenFPGA/libs/EXTERNAL/libargparse/src/argparse_default_converter.hpp

176 lines
5.5 KiB
C++

#ifndef ARGPARSE_DEFAULT_CONVERTER_HPP
#define ARGPARSE_DEFAULT_CONVERTER_HPP
#include <sstream>
#include <vector>
#include <typeinfo>
#include "argparse_error.hpp"
#include "argparse_util.hpp"
#include "argparse_value.hpp"
namespace argparse {
/*
* Get a useful description of the argument type
*/
//Signed Integer
template<typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, std::string>::type
arg_type() { return "integer"; }
//Unsigned Integer
template<typename T>
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, std::string>::type
arg_type() { return "non-negative integer"; }
//Float
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, std::string>::type
arg_type() { return "float"; }
//Unkown
template<typename T>
typename std::enable_if<!std::is_floating_point<T>::value && !std::is_integral<T>::value, std::string>::type
arg_type() { return ""; } //Empty
/*
* Default Conversions to/from strings
*/
template<typename T>
class DefaultConverter {
public:
ConvertedValue<T> from_str(std::string str) {
std::stringstream ss(str);
T val = T();
ss >> val;
bool eof = ss.eof();
bool fail = ss.fail();
bool converted_ok = eof && !fail;
ConvertedValue<T> converted_value;
if (!converted_ok) {
std::stringstream msg;
msg << "Invalid conversion from '" << str << "'";
std::string arg_type_str = arg_type<T>();
if (!arg_type_str.empty()) {
msg << " to " << arg_type_str;
}
converted_value.set_error(msg.str());
} else {
converted_value.set_value(val);
}
return converted_value;
}
ConvertedValue<std::string> to_str(T val) {
std::stringstream ss;
ss << val;
bool converted_ok = ss.eof() && !ss.fail();
ConvertedValue<std::string> converted_value;
if (!converted_ok) {
std::stringstream msg;
msg << "Invalid conversion from '" << val << "' to string";
converted_value.set_error(msg.str());
} else {
converted_value.set_value(ss.str());
}
return converted_value;
}
std::vector<std::string> default_choices() { return {}; }
};
//DefaultConverter specializations for bool
// By default std::stringstream doesn't accept "true" or "false"
// as boolean values.
template<>
class DefaultConverter<bool> {
public:
ConvertedValue<bool> from_str(std::string str) {
ConvertedValue<bool> converted_value;
str = tolower(str);
if (str == "0" || str == "false") {
converted_value.set_value(false);
} else if (str == "1" || str == "true") {
converted_value.set_value(true);
} else {
converted_value.set_error("Unexpected value '" + str + "' (expected one of: " + join(default_choices(), ", ") + ")");
}
return converted_value;
}
ConvertedValue<std::string> to_str(bool val) {
ConvertedValue<std::string> converted_value;
if (val) converted_value.set_value("true");
else converted_value.set_value("false");
return converted_value;
}
std::vector<std::string> default_choices() {
return {"true", "false"};
}
};
//DefaultConverter specializations for std::string
// The default conversion checks for eof() which is not set for empty strings,
// nessesitating the specialization
template<>
class DefaultConverter<std::string> {
public:
ConvertedValue<std::string> from_str(std::string str) {
ConvertedValue<std::string> converted_value;
converted_value.set_value(str);
return converted_value;
}
ConvertedValue<std::string> to_str(std::string val) {
ConvertedValue<std::string> converted_value;
converted_value.set_value(val);
return converted_value;
}
std::vector<std::string> default_choices() { return {}; }
};
//DefaultConverter specializations for const char*
// This allocates memory that the user is responsible for freeing
template<>
class DefaultConverter<const char*> {
public:
ConvertedValue<const char*> from_str(std::string str) {
ConvertedValue<const char*> val;
val.set_value(strdup(str.c_str()));
return val;
}
ConvertedValue<std::string> to_str(const char* val) {
ConvertedValue<std::string> converted_value;
converted_value.set_value(val);
return converted_value;
}
std::vector<std::string> default_choices() { return {}; }
};
//DefaultConverter specializations for char*
// This allocates memory that the user is responsible for freeing
template<>
class DefaultConverter<char*> {
public:
ConvertedValue<char*> from_str(std::string str) {
ConvertedValue<char*> val;
val.set_value(strdup(str.c_str()));
return val;
}
ConvertedValue<std::string> to_str(const char* val) {
ConvertedValue<std::string> converted_value;
converted_value.set_value(val);
return converted_value;
}
std::vector<std::string> default_choices() { return {}; }
};
} //namespace
#endif