Giriş
Custom validator yazmak için iki seçenek var.
1. operator >> içinde doğrulama yapmak
2. kendi tipimiz için validate() metodu yazmak.
operator>> metodu içinde
Örnek
Açıklaması şöyle.
Şöyle yaparız. operator >> içinde kendi chek_value() metodunu çağırırız.
Şöyle yaparız.
Elimizde kendi yapımız olsun
Custom validator yazmak için iki seçenek var.
1. operator >> içinde doğrulama yapmak
2. kendi tipimiz için validate() metodu yazmak.
operator>> metodu içinde
Örnek
Açıklaması şöyle.
...it's often easier to write a custom class for each option type. Normally program_options uses operator>> to decode the option value, so if you override this you get a chance to throw an exception that program_options recognises. If you use nested exceptions, you can print quite detailed error diagnostics.Örnek
Şöyle yaparız. operator >> içinde kendi chek_value() metodunu çağırırız.
// a custom option type
struct foo {
std::string value;
// check the value and throw a nested exception chain if it's wrong
void check_value() const
try {
if (value != "foo" and value != "bar") {
std::ostringstream ss;
ss << "value must be foo or bar, you supplied " << std::quoted(value);
throw std::invalid_argument(ss.str());
}
}
catch (...) {
std::throw_with_nested(po::validation_error(
po::validation_error::invalid_option_value,"foo"
));
}
}
// overload operators
friend std::istream &operator>>(std::istream &is, foo_or_bar &arg) {
is >> arg.value;
arg.check_value();
return is;
}
friend std::ostream &operator<<(std::ostream &os, foo_or_bar const &arg) {
return os << arg.value;
}
};
validate metodu
İmzası şöyle
Elimizde şöyle bir kod olsun
Şöyle yaparız. unsigned yerine nonnegative yapısını kullanırız.İmzası şöyle
void validate(boost::any &v, const std::vector<std::string> &values, Foo * , int);
ÖrnekElimizde şöyle bir kod olsun
namespace po = boost::program_options;
struct MyClass {
int x;
MyClass(int a) : x(a){};
friend std::ostream& operator<<(std::ostream& os, MyClass const& mc) {
return os << "MyClass(" << mc.x << ")";
}
};
void validate(boost::any &v, const std::vector<std::string> &values, MyClass * , int) {
v = MyClass(std::stoi(values.front()));
}
Çağırmak için şöyle yaparız.int main(int argc, char **argv) {
po::options_description desc("");
boost::optional<MyClass> my_option;
desc.add_options()("MyClass", po::value(&my_option), "MyClass");
po::variables_map args;
store(parse_command_line(argc, argv, desc), args);
notify(args);
std::cout << "Arg: " << my_option << "\n";
}
Örnek - validate metodustruct nonnegative {
unsigned value;
};
void validate(boost::any& v, const std::vector<std::string>& values,
nonnegative*, int)
{
using namespace boost::program_options;
validators::check_first_occurrence(v);
std::string const& s = validators::get_single_string(values);
if (s[0] == '-') {
throw validation_error(validation_error::invalid_option_value);
}
v = lexical_cast<unsigned>(s);
}
Örnek - validate metoduŞöyle yaparız.
enum class Ipc : int8_t
{
TCP = 0,
UDP,
};
// This function is called for arguments of the type Ipc
void validate(boost::any& v, const vector<string>& values, Ipc*, int)
{
po::validators::check_first_occurrence(v);
const string& enteredValue = po::validators::get_single_string(values);
const string& enteredValueUpper = boost::to_upper_copy(enteredValue);
if (enteredValueUpper == "TCP")
{
v = boost::any(Ipc::TCP);
}
else if (enteredValueUpper == "UPD")
{
v = boost::any(Ipc::UDP);
}
else
{
throw po::validation_error(enteredValue);
}
}
Hata varsa exception'daki mesaj şöyledir.error: the argument for option '--ipc' is invalid: shm
Şu şekilde fırlatırsak hatalı girdiyi göremeyiz.throw po::validation_error(po::validation_error::invalid_option_value, enteredValue);
Çıktı olarak şunu alırız.error: the argument for option '--ipc' is invalid
Örnek - validate metoduElimizde kendi yapımız olsun
using clock = std::chrono::steady_clock;
struct duration {
clock::duration value;
friend std::ostream& operator<<(std::ostream& os, duration const& holder) {
using namespace std::chrono;
auto ms = duration_cast<milliseconds>(holder.value).count();
if (ms >= 1000)
return os << (ms/1000) << "s";
else
return os << ms << "ms";
}
};
Şöyle yaparız.template<class charT>
void validate(boost::any& v, const std::vector< std::basic_string<charT> >& xs,
duration*, long)
{
po::validators::check_first_occurrence(v);
std::basic_string<charT> s(po::validators::get_single_string(xs));
int magnitude;
clock::duration factor;
namespace qi = boost::spirit::qi;
qi::symbols<char, clock::duration> unit;
unit.add("s",1s)("ms",1ms)("us",1us)("µs",1us)("m",1min)("h",1h);
if (parse(s.begin(), s.end(), qi::int_ >> unit >> qi::eoi, magnitude, factor))
v = duration {magnitude * factor};
else
throw po::invalid_option_value(s);
}
Hiç yorum yok:
Yorum Gönder