13
0

Error checking string to int conversion from midnam files.

Use const references where appropriate.
Fix incorrect use of (either confusingly named or often abused) Patch tag Number attribute.

git-svn-id: svn://localhost/ardour2/branches/3.0@13923 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2013-01-20 07:33:27 +00:00
parent 022e590429
commit 64f1a8e893
2 changed files with 55 additions and 50 deletions

View File

@ -362,9 +362,9 @@ public:
const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(std::string mode_name);
boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(std::string mode, uint8_t channel);
boost::shared_ptr<Patch> find_patch(std::string mode, uint8_t channel, const PatchPrimaryKey& key);
boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(const std::string& mode_name);
boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(const std::string& mode, uint8_t channel);
boost::shared_ptr<Patch> find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key);
boost::shared_ptr<NoteNameList> note_name_list(const std::string& name);
boost::shared_ptr<ChannelNameSet> channel_name_set(const std::string& name);

View File

@ -14,10 +14,10 @@
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 <stdlib.h>
#include <algorithm>
#include <iostream>
@ -42,7 +42,21 @@ Patch::Patch (std::string name, uint8_t p_number, uint16_t b_number)
{
}
int initialize_primary_key_from_commands (PatchPrimaryKey& id, const XMLNode* node)
static int
string_to_int(const XMLTree& tree, const std::string& str)
{
char* endptr = NULL;
const int i = strtol(str.c_str(), &endptr, 10);
if (str.empty() || *endptr != '\0') {
PBD::error << string_compose("%1: Bad number `%2'", tree.filename(), str)
<< endmsg;
}
return i;
}
static int
initialize_primary_key_from_commands (
const XMLTree& tree, PatchPrimaryKey& id, const XMLNode* node)
{
id.bank_number = 0;
@ -51,21 +65,19 @@ int initialize_primary_key_from_commands (PatchPrimaryKey& id, const XMLNode* no
XMLNode* node = *i;
if (node->name() == "ControlChange") {
string control = node->property("Control")->value();
assert(control != "");
string value = node->property("Value")->value();
assert(value != "");
const string& control = node->property("Control")->value();
const string& value = node->property("Value")->value();
if (control == "0") {
id.bank_number |= (PBD::atoi (value)) << 7;
id.bank_number |= string_to_int(tree, value) << 7;
} else if (control == "32") {
id.bank_number |= PBD::atoi (value);
id.bank_number |= string_to_int(tree, value);
}
} else if (node->name() == "ProgramChange") {
string number = node->property("Number")->value();
const string& number = node->property("Number")->value();
assert(number != "");
id.program_number = PBD::atoi(number);
id.program_number = string_to_int(tree, number);
}
}
@ -96,37 +108,33 @@ Patch::get_state (void)
}
int
Patch::set_state (const XMLTree&, const XMLNode& node)
Patch::set_state (const XMLTree& tree, const XMLNode& node)
{
if (node.name() != "Patch") {
cerr << "Incorrect node " << node.name() << " handed to Patch" << endl;
return -1;
}
const XMLProperty* prop = node.property ("Number");
/* Note there is a "Number" attribute, but it's really more like a label
and is often not numeric. We currently do not use it. */
if (!prop) {
const XMLProperty* program_change = node.property("ProgramChange");
if (program_change) {
_id.program_number = string_to_int(tree, program_change->value());
}
const XMLProperty* name = node.property("Name");
if (!name) {
return -1;
}
_id.program_number = PBD::atoi (prop->value());
prop = node.property ("Name");
if (!prop) {
return -1;
}
_name = prop->value();
_name = name->value();
XMLNode* commands = node.child("PatchMIDICommands");
if (commands) {
if (initialize_primary_key_from_commands(_id, commands)) {
return -1;
if (initialize_primary_key_from_commands(tree, _id, commands) &&
!program_change) {
return -1; // Failed to find a program number anywhere
}
} else {
string program_change = node.property("ProgramChange")->value();
assert(program_change.length());
_id.program_number = PBD::atoi(program_change);
}
XMLNode* use_note_name_list = node.child("UsesNoteNameList");
@ -152,21 +160,17 @@ Note::set_state (const XMLTree& tree, const XMLNode& node)
{
assert(node.name() == "Note");
/* If the note number is junk, this will pull a number from the start, or
return zero if there isn't one. The decrement will make that zero
illegal since note numbers in the file are one-based. Better error
detection would be a good idea, but the duplicate check in
NoteNameList::set_state() will probably catch most errors anyway. */
_number = atoi(node.property("Number")->value().c_str()) - 1;
_name = node.property("Name")->value();
if (_number > 127) {
const int num = string_to_int(tree, node.property("Number")->value());
if (num < 1 || num > 128) {
PBD::warning << string_compose("%1: Note number %2 (%3) out of range",
tree.filename(), (int)_number, _name)
tree.filename(), num, _name)
<< endmsg;
return -1;
}
_number = num - 1;
_name = node.property("Name")->value();
return 0;
}
@ -297,7 +301,7 @@ PatchBank::set_state (const XMLTree& tree, const XMLNode& node)
XMLNode* commands = node.child("MIDICommands");
if (commands) {
PatchPrimaryKey id (0, 0);
if (initialize_primary_key_from_commands (id, commands)) {
if (initialize_primary_key_from_commands (tree, id, commands)) {
return -1;
}
_number = id.bank_number;
@ -439,7 +443,8 @@ ChannelNameSet::set_state (const XMLTree& tree, const XMLNode& node)
for(XMLSharedNodeList::const_iterator i = channels->begin();
i != channels->end();
++i) {
_available_for_channels.insert(atoi((*i)->attribute_value().c_str()));
_available_for_channels.insert(
string_to_int(tree, (*i)->attribute_value()));
}
}
@ -476,8 +481,8 @@ CustomDeviceMode::set_state(const XMLTree& tree, const XMLNode& a_node)
for(XMLSharedNodeList::const_iterator i = channel_name_set_assignments->begin();
i != channel_name_set_assignments->end();
++i) {
int channel = atoi((*i)->property("Channel")->value().c_str());
string name_set = (*i)->property("NameSet")->value();
const int channel = string_to_int(tree, (*i)->property("Channel")->value());
const string& name_set = (*i)->property("NameSet")->value();
assert( 1 <= channel && channel <= 16 );
_channel_name_set_assignments[channel - 1] = name_set;
}
@ -502,13 +507,13 @@ CustomDeviceMode::get_state(void)
}
boost::shared_ptr<CustomDeviceMode>
MasterDeviceNames::custom_device_mode_by_name(std::string mode_name)
MasterDeviceNames::custom_device_mode_by_name(const std::string& mode_name)
{
return _custom_device_modes[mode_name];
}
boost::shared_ptr<ChannelNameSet>
MasterDeviceNames::channel_name_set_by_device_mode_and_channel(std::string mode, uint8_t channel)
MasterDeviceNames::channel_name_set_by_device_mode_and_channel(const std::string& mode, uint8_t channel)
{
boost::shared_ptr<CustomDeviceMode> cdm = custom_device_mode_by_name(mode);
boost::shared_ptr<ChannelNameSet> cns = _channel_name_sets[cdm->channel_name_set_name_by_channel(channel)];
@ -516,7 +521,7 @@ MasterDeviceNames::channel_name_set_by_device_mode_and_channel(std::string mode,
}
boost::shared_ptr<Patch>
MasterDeviceNames::find_patch(std::string mode, uint8_t channel, const PatchPrimaryKey& key)
MasterDeviceNames::find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key)
{
return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key);
}
@ -668,7 +673,7 @@ MasterDeviceNames::set_state(const XMLTree& tree, const XMLNode&)
PatchNameLists::iterator p;
for (ChannelNameSet::PatchBanks::iterator pb = pbs.begin(); pb != pbs.end(); ++pb) {
std::string pln = (*pb)->patch_list_name();
const std::string& pln = (*pb)->patch_list_name();
if (!pln.empty()) {
if ((p = _patch_name_lists.find (pln)) != _patch_name_lists.end()) {
if ((*pb)->set_patch_name_list (p->second)) {