diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-06-02 21:41:35 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-06-02 21:41:35 +0000 |
commit | 449aab3c465bbbf66d221fac3d7ea559f1720357 (patch) | |
tree | 6843cc40c88250a132acac701271f1504cd2df04 /libs/pbd/enumwriter.cc | |
parent | 9c0d7d72d70082a54f823cd44c0ccda5da64bb6f (diff) |
rollback to 3428, before the mysterious removal of libs/* at 3431/3432
git-svn-id: svn://localhost/ardour2/branches/3.0@3435 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/enumwriter.cc')
-rw-r--r-- | libs/pbd/enumwriter.cc | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/libs/pbd/enumwriter.cc b/libs/pbd/enumwriter.cc new file mode 100644 index 0000000000..7674410ec9 --- /dev/null +++ b/libs/pbd/enumwriter.cc @@ -0,0 +1,273 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include <ctype.h> + +#include <string.h> +#include <stdlib.h> + +#include <pbd/enumwriter.h> +#include <pbd/error.h> +#include <pbd/compose.h> + +using namespace std; +using namespace PBD; + +#include "i18n.h" + +EnumWriter* EnumWriter::_instance = 0; +map<string,string> EnumWriter::hack_table; + +static int +nocase_cmp(const string & s1, const string& s2) +{ + string::const_iterator it1 = s1.begin(); + string::const_iterator it2 = s2.begin(); + + while ((it1 != s1.end()) && (it2 != s2.end())) { + if(::toupper(*it1) != ::toupper(*it2)) {//letters differ? + // return -1 to indicate 'smaller than', 1 otherwise + return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1; + } + + ++it1; + ++it2; + } + + string::size_type size1 = s1.size(); + string::size_type size2 = s2.size(); + + //return -1,0 or 1 according to strings' lengths + + if (size1 == size2) { + return 0; + } + + return (size1 < size2) ? -1 : 1; +} + +EnumWriter::EnumWriter () +{ + if (_instance == 0) { + _instance = this; + } +} + +EnumWriter::~EnumWriter () +{ +} + +void +EnumWriter::register_distinct (string type, vector<int> v, vector<string> s) +{ + pair<string,EnumRegistration> newpair; + pair<Registry::iterator,bool> result; + + newpair.first = type; + newpair.second = EnumRegistration (v, s, false); + + result = registry.insert (newpair); + + if (!result.second) { + warning << string_compose (_("enum type \"%1\" already registered with the enum writer"), type) << endmsg; + } +} + +void +EnumWriter::register_bits (string type, vector<int> v, vector<string> s) +{ + pair<string,EnumRegistration> newpair; + pair<Registry::iterator,bool> result; + + newpair.first = type; + newpair.second = EnumRegistration (v, s, true); + + result = registry.insert (newpair); + + if (!result.second) { + warning << _("enum type \"%1\" already registered with the enum writer") << endmsg; + } +} + +string +EnumWriter::write (string type, int value) +{ + Registry::iterator x = registry.find (type); + + if (x == registry.end()) { + error << string_compose (_("EnumWriter: unknown enumeration type \"%1\""), type) << endmsg; + throw unknown_enumeration(); + } + + if (x->second.bitwise) { + return write_bits (x->second, value); + } else { + return write_distinct (x->second, value); + } +} + +int +EnumWriter::read (string type, string value) +{ + Registry::iterator x = registry.find (type); + + if (x == registry.end()) { + error << string_compose (_("EnumWriter: unknown enumeration type \"%1\""), type) << endmsg; + throw unknown_enumeration(); + } + + if (x->second.bitwise) { + return read_bits (x->second, value); + } else { + return read_distinct (x->second, value); + } +} + +string +EnumWriter::write_bits (EnumRegistration& er, int value) +{ + vector<int>::iterator i; + vector<string>::iterator s; + string result; + + for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) { + if (value & (*i)) { + if (!result.empty()) { + result += ','; + } + result += (*s); + } + } + + return result; +} + +string +EnumWriter::write_distinct (EnumRegistration& er, int value) +{ + vector<int>::iterator i; + vector<string>::iterator s; + + for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) { + if (value == (*i)) { + return (*s); + } + } + + return string(); +} + +int +EnumWriter::read_bits (EnumRegistration& er, string str) +{ + vector<int>::iterator i; + vector<string>::iterator s; + int result = 0; + bool found = false; + string::size_type comma; + + /* catch old-style hex numerics */ + + if (str.length() > 2 && str[0] == '0' && str[1] == 'x') { + return strtol (str.c_str(), (char **) 0, 16); + } + + /* catch old style dec numerics */ + + if (strspn (str.c_str(), "0123456789") == str.length()) { + return strtol (str.c_str(), (char **) 0, 10); + } + + do { + + comma = str.find_first_of (','); + string segment = str.substr (0, comma); + + for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) { + if (segment == *s || nocase_cmp (segment, *s) == 0) { + result |= (*i); + found = true; + } + } + + if (comma == string::npos) { + break; + } + + str = str.substr (comma+1); + + } while (true); + + if (!found) { + throw unknown_enumeration(); + } + + return result; +} + +int +EnumWriter::read_distinct (EnumRegistration& er, string str) +{ + vector<int>::iterator i; + vector<string>::iterator s; + + /* catch old-style hex numerics */ + + if (str.length() > 2 && str[0] == '0' && str[1] == 'x') { + return strtol (str.c_str(), (char **) 0, 16); + } + + /* catch old style dec numerics */ + + if (strspn (str.c_str(), "0123456789") == str.length()) { + return strtol (str.c_str(), (char **) 0, 10); + } + + for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) { + if (str == (*s) || nocase_cmp (str, *s) == 0) { + return (*i); + } + } + + /* failed to find it as-is. check to see if there a hack for the name we're looking up */ + + map<string,string>::iterator x; + + if ((x = hack_table.find (str)) != hack_table.end()) { + + cerr << "found hack for " << str << " = " << x->second << endl; + + str = x->second; + + for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) { + if (str == (*s) || nocase_cmp (str, *s) == 0) { + return (*i); + } + } + } + + throw unknown_enumeration(); +} + +void +EnumWriter::add_to_hack_table (string str, string hacked) +{ + hack_table[str] = hacked; +} |