2 Copyright (C) 2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "pbd/enumwriter.h"
27 #include "pbd/error.h"
28 #include "pbd/compose.h"
35 EnumWriter
* EnumWriter::_instance
= 0;
36 map
<string
,string
> EnumWriter::hack_table
;
39 nocase_cmp(const string
& s1
, const string
& s2
)
41 string::const_iterator it1
= s1
.begin();
42 string::const_iterator it2
= s2
.begin();
44 while ((it1
!= s1
.end()) && (it2
!= s2
.end())) {
45 if(::toupper(*it1
) != ::toupper(*it2
)) {//letters differ?
46 // return -1 to indicate 'smaller than', 1 otherwise
47 return (::toupper(*it1
) < ::toupper(*it2
)) ? -1 : 1;
54 string::size_type size1
= s1
.size();
55 string::size_type size2
= s2
.size();
57 //return -1,0 or 1 according to strings' lengths
63 return (size1
< size2
) ? -1 : 1;
67 EnumWriter::instance()
70 _instance
= new EnumWriter
;
76 EnumWriter::EnumWriter ()
80 EnumWriter::~EnumWriter ()
85 EnumWriter::register_distinct (string type
, vector
<int> v
, vector
<string
> s
)
87 pair
<string
,EnumRegistration
> newpair
;
88 pair
<Registry::iterator
,bool> result
;
91 newpair
.second
= EnumRegistration (v
, s
, false);
93 result
= registry
.insert (newpair
);
96 warning
<< string_compose (_("enum type \"%1\" already registered with the enum writer"), type
) << endmsg
;
101 EnumWriter::register_bits (string type
, vector
<int> v
, vector
<string
> s
)
103 pair
<string
,EnumRegistration
> newpair
;
104 pair
<Registry::iterator
,bool> result
;
106 newpair
.first
= type
;
107 newpair
.second
= EnumRegistration (v
, s
, true);
109 result
= registry
.insert (newpair
);
111 if (!result
.second
) {
112 warning
<< _("enum type \"%1\" already registered with the enum writer") << endmsg
;
117 EnumWriter::write (string type
, int value
)
119 Registry::iterator x
= registry
.find (type
);
121 if (x
== registry
.end()) {
122 error
<< string_compose (_("EnumWriter: unknown enumeration type \"%1\""), type
) << endmsg
;
123 throw unknown_enumeration();
126 if (x
->second
.bitwise
) {
127 return write_bits (x
->second
, value
);
129 return write_distinct (x
->second
, value
);
134 EnumWriter::read (string type
, string value
)
136 Registry::iterator x
= registry
.find (type
);
138 if (x
== registry
.end()) {
139 error
<< string_compose (_("EnumWriter: unknown enumeration type \"%1\""), type
) << endmsg
;
140 throw unknown_enumeration();
143 if (x
->second
.bitwise
) {
144 return read_bits (x
->second
, value
);
146 return read_distinct (x
->second
, value
);
151 EnumWriter::write_bits (EnumRegistration
& er
, int value
)
153 vector
<int>::iterator i
;
154 vector
<string
>::iterator s
;
157 for (i
= er
.values
.begin(), s
= er
.names
.begin(); i
!= er
.values
.end(); ++i
, ++s
) {
159 if (!result
.empty()) {
170 EnumWriter::write_distinct (EnumRegistration
& er
, int value
)
172 vector
<int>::iterator i
;
173 vector
<string
>::iterator s
;
175 for (i
= er
.values
.begin(), s
= er
.names
.begin(); i
!= er
.values
.end(); ++i
, ++s
) {
185 EnumWriter::validate (EnumRegistration
& er
, int val
)
187 if (er
.values
.empty()) {
192 /* zero is always a legal value for our enumerations, just about
197 vector
<int>::iterator i
;
198 string enum_name
= _("unknown enumeration");
200 for (Registry::iterator x
= registry
.begin(); x
!= registry
.end(); ++x
) {
201 if (&er
== &(*x
).second
) {
202 enum_name
= (*x
).first
;
207 for (i
= er
.values
.begin(); i
!= er
.values
.end(); ++i
) {
213 warning
<< string_compose (_("Illegal value loaded for %1 (%2) - %3 used instead"),
214 enum_name
, val
, er
.names
.front())
216 return er
.values
.front();
220 EnumWriter::read_bits (EnumRegistration
& er
, string str
)
222 vector
<int>::iterator i
;
223 vector
<string
>::iterator s
;
226 string::size_type comma
;
228 /* catch old-style hex numerics */
230 if (str
.length() > 2 && str
[0] == '0' && str
[1] == 'x') {
231 int val
= strtol (str
.c_str(), (char **) 0, 16);
232 return validate (er
, val
);
235 /* catch old style dec numerics */
237 if (strspn (str
.c_str(), "0123456789") == str
.length()) {
238 int val
= strtol (str
.c_str(), (char **) 0, 10);
239 return validate (er
, val
);
244 comma
= str
.find_first_of (',');
245 string segment
= str
.substr (0, comma
);
247 for (i
= er
.values
.begin(), s
= er
.names
.begin(); i
!= er
.values
.end(); ++i
, ++s
) {
248 if (segment
== *s
|| nocase_cmp (segment
, *s
) == 0) {
254 if (comma
== string::npos
) {
258 str
= str
.substr (comma
+1);
263 throw unknown_enumeration();
270 EnumWriter::read_distinct (EnumRegistration
& er
, string str
)
272 vector
<int>::iterator i
;
273 vector
<string
>::iterator s
;
275 /* catch old-style hex numerics */
277 if (str
.length() > 2 && str
[0] == '0' && str
[1] == 'x') {
278 int val
= strtol (str
.c_str(), (char **) 0, 16);
279 return validate (er
, val
);
282 /* catch old style dec numerics */
284 if (strspn (str
.c_str(), "0123456789") == str
.length()) {
285 int val
= strtol (str
.c_str(), (char **) 0, 10);
286 return validate (er
, val
);
289 for (i
= er
.values
.begin(), s
= er
.names
.begin(); i
!= er
.values
.end(); ++i
, ++s
) {
290 if (str
== (*s
) || nocase_cmp (str
, *s
) == 0) {
295 /* failed to find it as-is. check to see if there a hack for the name we're looking up */
297 map
<string
,string
>::iterator x
;
299 if ((x
= hack_table
.find (str
)) != hack_table
.end()) {
301 cerr
<< "found hack for " << str
<< " = " << x
->second
<< endl
;
305 for (i
= er
.values
.begin(), s
= er
.names
.begin(); i
!= er
.values
.end(); ++i
, ++s
) {
306 if (str
== (*s
) || nocase_cmp (str
, *s
) == 0) {
312 throw unknown_enumeration();
316 EnumWriter::add_to_hack_table (string str
, string hacked
)
318 hack_table
[str
] = hacked
;