provide enumeration value validation during loading of configuration variables (and other) - if the loaded value isn't a legal enum value, the first registered legal value will be used instead

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@7824 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-09-21 20:44:57 +00:00
parent 13f05dc115
commit d1771add39
3 changed files with 105 additions and 13 deletions

View file

@ -24,6 +24,7 @@
#include <ostream>
#include <pbd/xml++.h>
#include <pbd/enumwriter.h>
#include "ardour/utils.h"
@ -113,9 +114,9 @@ class ConfigVariable : public ConfigVariableBase
if ((prop = child->property ("name")) != 0) {
if (prop->value() == _name) {
if ((prop = child->property ("value")) != 0) {
std::stringstream ss;
ss << prop->value();
ss >> value;
std::stringstream ss;
ss << enum_validate (value, prop->value());
ss >> value;
_owner = (ConfigVariableBase::Owner)(_owner |owner);
return true;
}
@ -138,12 +139,12 @@ class ConfigVariable : public ConfigVariableBase
for (oiter = olist.begin(); oiter != olist.end(); ++oiter) {
option = *oiter;
if (option->name() == _name) {
if ((opt_prop = option->property ("val")) != 0) {
std::stringstream ss;
ss << opt_prop->value();
ss >> value;
std::stringstream ss;
ss << enum_validate (value, opt_prop->value());
ss >> value;
_owner = (ConfigVariableBase::Owner)(_owner |owner);
return true;
}

View file

@ -174,6 +174,83 @@ EnumWriter::write_distinct (EnumRegistration& er, int value)
return string();
}
string
EnumWriter::validate_string (EnumRegistration& er, const string& str)
{
if (er.values.empty()) {
return str;
}
vector<int>::iterator i;
int val = atoi (str.c_str());
for (i = er.values.begin(); i != er.values.end(); ++i) {
if (*i == val) {
return str; /* string is a legal representation of a enumerated value */
}
}
string enum_name = _("unknown enumeration");
for (Registry::iterator x = registry.begin(); x != registry.end(); ++x) {
if (&er == &(*x).second) {
enum_name = (*x).first;
}
}
warning << string_compose (_("Illegal value loaded for %1 (%2) - %3 used instead"),
enum_name, val, er.names.front())
<< endmsg;
stringstream ss;
ss << er.values.front();
return ss.str();
}
string
EnumWriter::typed_validate (const string& type, const string& value_str)
{
for (Registry::iterator x = registry.begin(); x != registry.end(); ++x) {
if (x->first == type) {
return validate_string (x->second, value_str);
}
}
/* not a known enum */
return value_str;
}
int
EnumWriter::validate (EnumRegistration& er, int val)
{
if (er.values.empty()) {
return val;
}
vector<int>::iterator i;
string enum_name = _("unknown enumeration");
for (Registry::iterator x = registry.begin(); x != registry.end(); ++x) {
if (&er == &(*x).second) {
enum_name = (*x).first;
}
}
for (i = er.values.begin(); i != er.values.end(); ++i) {
if (*i == val) {
return val;
}
}
warning << string_compose (_("Illegal value loaded for %1 (%2) - %3 used instead"),
enum_name, val, er.names.front())
<< endmsg;
return er.values.front();
}
int
EnumWriter::read_bits (EnumRegistration& er, string str)
{
@ -186,14 +263,16 @@ EnumWriter::read_bits (EnumRegistration& er, string str)
/* catch old-style hex numerics */
if (str.length() > 2 && str[0] == '0' && str[1] == 'x') {
return strtol (str.c_str(), (char **) 0, 16);
int val = strtol (str.c_str(), (char **) 0, 16);
return validate (er, val);
}
/* catch old style dec numerics */
if (strspn (str.c_str(), "0123456789") == str.length()) {
return strtol (str.c_str(), (char **) 0, 10);
}
int val = strtol (str.c_str(), (char **) 0, 10);
return validate (er, val);
}
do {
@ -231,14 +310,16 @@ EnumWriter::read_distinct (EnumRegistration& er, string str)
/* catch old-style hex numerics */
if (str.length() > 2 && str[0] == '0' && str[1] == 'x') {
return strtol (str.c_str(), (char **) 0, 16);
int val = strtol (str.c_str(), (char **) 0, 16);
return validate (er, val);
}
/* catch old style dec numerics */
if (strspn (str.c_str(), "0123456789") == str.length()) {
return strtol (str.c_str(), (char **) 0, 10);
}
int val = strtol (str.c_str(), (char **) 0, 10);
return validate (er, val);
}
for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) {
if (str == (*s) || nocase_cmp (str, *s) == 0) {

View file

@ -18,6 +18,9 @@
$Id$
*/
#ifndef __pbd_enumwriter_h__
#define __pbd_enumwriter_h__
#include <map>
#include <string>
#include <vector>
@ -45,6 +48,7 @@ class EnumWriter {
int read (std::string type, std::string value);
void add_to_hack_table (std::string str, std::string hacked_str);
std::string typed_validate (const std::string& type, const std::string&);
private:
struct EnumRegistration {
@ -68,10 +72,16 @@ class EnumWriter {
static EnumWriter* _instance;
static std::map<std::string,std::string> hack_table;
int validate (EnumRegistration& er, int value);
std::string validate_string (EnumRegistration& er, const std::string&);
};
}
#define enum_validate(v,str) PBD::EnumWriter::instance().typed_validate (typeid(v).name(),str)
#define enum_2_string(e) (PBD::EnumWriter::instance().write (typeid(e).name(), e))
#define string_2_enum(str,e) (PBD::EnumWriter::instance().read (typeid(e).name(), (str)))
#endif /* __pbd_enumwriter_h__ */