void OptionsFunctionalityNode::addOption(const string &name, const opt_type& type, const GenericType &def_val, const string& desc, const std::vector<GenericType> &allowed_vals, bool inherit){ // If inheriting, check if the type matches if (inherit && allowed_options.find(name)!=allowed_options.end()) { casadi_assert_message(allowed_options[name] == type, "The option '" << name << "' was indicated to inherit, but the type definition of the ancestor '" << GenericType::get_type_description(allowed_options[name]) << "' conflicts with the type definition here '" << GenericType::get_type_description(type) << "'." ); } defaults_[name] = def_val; allowed_options[name] = type; std::vector<GenericType> allowed_vals_vec; // Inherit allowed_vals if (inherit && allowed_vals_.find(name)!=allowed_vals_.end()) { allowed_vals_vec.insert( allowed_vals_vec.end(), allowed_vals_[name].begin(), allowed_vals_[name].end() ); } // Insert current allowed_vals allowed_vals_vec.insert( allowed_vals_vec.end(), allowed_vals.begin(), allowed_vals.end() ); if(!def_val.isNull()) dictionary_[name] = def_val; // Inherit description std::stringstream s; if (inherit && description_.find(name)!=description_.end()) { s << description_[name]; if (!desc.empty()) s << std::endl; } // Insert current description s << desc; description_[name] = s.str(); allowed_vals_[name] = allowed_vals_vec; }
void OptionsFunctionalityNode::setOption(const string &name, const GenericType &op) { assert_exists(name); // If we have an empty vector, than we are not strict about the type if (op.isEmptyVector()) { dictionary_[name] = GenericType::from_type(allowed_options[name]); return; } // Some typechecking if (!op.can_cast_to(allowed_options[name]) && !op.isNull()) { stringstream ss; ss << "Option '" << name << "' expects a '" << GenericType::get_type_description(allowed_options[name]) << "' type." << endl; if (op.getType() == OT_BOOLEAN) { ss << "You supplied another type, possibly boolean." << endl; if (allowed_options[name]==OT_REAL || allowed_options[name]==OT_INTEGER) { ss << "(A common mistake is to use SX/MX instead of floats/DMatrix in this context)" << endl; } } else { ss << "You supplied a type '" << op.get_description() << "' instead." << endl; } if (!allowed_vals_[name].empty()) { ss << "(Allowed values are:"; for (std::vector<GenericType>::const_iterator it=allowed_vals_[name].begin(); it!=allowed_vals_[name].end();it++) { ss << " '" << *it << "'"; } ss << ")" << endl; } casadi_error(ss.str()); } // If allowed values are listed, check them. if (!allowed_vals_[name].empty()) { bool found; GenericType problem = op; if (op.isStringVector()) { found = true; const std::vector<std::string> & opv = op.toStringVector(); for (std::vector<std::string>::const_iterator it=opv.begin();it!=opv.end();it++) { std::cout << "checking " << *it << std::endl; if (std::find(allowed_vals_[name].begin(), allowed_vals_[name].end(), (*it))==allowed_vals_[name].end()) { problem = (*it); found = false; break; } } } else { found = false; for (std::vector<GenericType>::const_iterator it=allowed_vals_[name].begin(); it!=allowed_vals_[name].end();it++) { found = found || (*it) == op; } } // If supplied op is not in allowed values, raise an error. if (!found) { stringstream ss; ss << "Option '" << name << "' does not allow '" << problem << "'." << endl; ss << "(Allowed values options are:"; for (std::vector<GenericType>::const_iterator it=allowed_vals_[name].begin(); it!=allowed_vals_[name].end();it++) { ss << " '" << *it << "'"; } ss << ")" << endl; casadi_error(ss.str()); } } // Save the option dictionary_[name] = op; }