in src/model_server/lib/extensions/option_info.cpp [55:286]
flexible_type option_info::interpret_value(const flexible_type& value) const {
std::string sep_char = (value.get_type() == flex_type_enum::STRING) ? "'" : "";
flexible_type ret_v;
switch(parameter_type) {
case option_info::REAL:
{
bool value_type_okay = false;
switch(value.get_type()) {
case flex_type_enum::INTEGER:
ret_v = double(value);
value_type_okay = true;
break;
case flex_type_enum::FLOAT:
ret_v = value;
value_type_okay = true;
break;
case flex_type_enum::STRING:
{
try {
ret_v = boost::lexical_cast<double>(value.get<flex_string>());
value_type_okay = true;
} catch(const boost::bad_lexical_cast&) {
value_type_okay = false;
}
break;
}
case flex_type_enum::UNDEFINED:
ret_v = default_value;
value_type_okay = true;
break;
default:
value_type_okay = false;
break;
}
if(!value_type_okay) {
std::ostringstream msg;
msg << "Expected numeric value for option '" << name
<< "'. Cannot cast " << sep_char << value << sep_char
<< " to a numeric value.";
log_and_throw(msg.str());
}
if( (!(double(ret_v) >= lower_bound)) || (!(double(ret_v) <= upper_bound))) {
std::ostringstream msg;
msg << "Option '" << name << "' must be in the range ["
<< lower_bound << ", " << upper_bound << "].";
log_and_throw(msg.str());
}
break;
}
case option_info::INTEGER:
{
bool value_type_okay = false;
switch(value.get_type()) {
case flex_type_enum::INTEGER:
ret_v = value;
value_type_okay = true;
break;
case flex_type_enum::FLOAT:
ret_v = int64_t(value.get<double>());
if(double(ret_v) != value.get<double>())
value_type_okay = false;
else
value_type_okay = true;
break;
case flex_type_enum::STRING:
{
try {
ret_v = boost::lexical_cast<int64_t>(value.get<flex_string>());
value_type_okay = true;
} catch(const boost::bad_lexical_cast&) {
value_type_okay = false;
}
break;
}
case flex_type_enum::UNDEFINED:
ret_v = default_value;
value_type_okay = true;
break;
default:
value_type_okay = false;
break;
}
if(!value_type_okay) {
std::ostringstream msg;
msg << "Expected integer value for option '" << name
<< "'. Cannot cast " << sep_char << value << sep_char
<< " to an integer value.";
log_and_throw(msg.str());
}
if( (!(flex_int(ret_v) >= lower_bound)) || (!(flex_int(ret_v) <= upper_bound))) {
std::ostringstream msg;
msg << "Option '" << name << "' must be in the range ["
<< lower_bound << ", " << upper_bound << "].";
log_and_throw(msg.str());
}
break;
}
case option_info::BOOL:
{
bool value_type_okay = false;
switch(value.get_type()) {
case flex_type_enum::INTEGER:
if(value.get<flex_int>() == 0) {
ret_v = false;
value_type_okay = true;
} else if (value.get<flex_int>() == 1) {
ret_v = true;
value_type_okay = true;
} else {
value_type_okay = false;
}
break;
case flex_type_enum::FLOAT:
if(value.get<flex_float>() == 0.0) {
ret_v = false;
value_type_okay = true;
} else if (value.get<flex_float>() == 1.0) {
ret_v = true;
value_type_okay = true;
} else {
value_type_okay = false;
}
break;
case flex_type_enum::STRING:
{
static const std::map<std::string, bool> okay_values =
{ {"1", true},
{"True", true},
{"T", true},
{"true", true},
{"Y", true},
{"y", true},
{"yes", true},
{"0", false},
{"False", false},
{"F", false},
{"false", false},
{"N", false},
{"n", false},
{"no", false} };
auto it = okay_values.find(value.get<flex_string>());
if(it != okay_values.end()) {
ret_v = it->second;
value_type_okay = true;
} else {
value_type_okay = false;
}
}
case flex_type_enum::UNDEFINED:
ret_v = default_value;
value_type_okay = true;
break;
default:
value_type_okay = false;
break;
}
if(!value_type_okay) {
std::ostringstream msg;
msg << "Expected boolean value for option '" << name << sep_char
<< "'. Cannot interpret " << sep_char << value << sep_char
<< " as True or False.";
log_and_throw(msg.str());
}
break;
}
case option_info::CATEGORICAL:
{
DASSERT_EQ(std::set<flexible_type>(allowed_values.begin(),
allowed_values.end()).count(default_value), 1);
bool is_okay = false;
for(const auto& okay_v : allowed_values) {
if(value == okay_v) {
is_okay = true;
break;
}
}
if(!is_okay){
std::ostringstream msg;
msg << "Option '" << name << "' must be one of (";
for(size_t i = 0; i < allowed_values.size()-1; i++){
msg << sep_char << allowed_values[i] << sep_char << ", ";
}
msg << "or " << sep_char << allowed_values[allowed_values.size()-1]
<< sep_char << ").";
log_and_throw(msg.str());
}
ret_v = value;
break;
}
case option_info::STRING:
ret_v = value;
// Maybe more on this later?
break;
case option_info::FLEXIBLE_TYPE:
ret_v = value;
break;
default:
log_and_throw("Internal error. Option type un-implemented");
break;
}
return ret_v;
}