summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/softlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/softlist.cpp')
-rw-r--r--src/emu/softlist.cpp455
1 files changed, 277 insertions, 178 deletions
diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp
index b4dba456a4a..35639f57d2e 100644
--- a/src/emu/softlist.cpp
+++ b/src/emu/softlist.cpp
@@ -21,7 +21,7 @@
// TYPE DEFINITIONS
//**************************************************************************
-typedef std::unordered_map<std::string,software_info *> softlist_map;
+typedef std::unordered_map<std::string,const software_info *> softlist_map;
// ======================> softlist_parser
@@ -44,7 +44,7 @@ private:
// internal parsing helpers
const char *filename() const { return m_list.filename(); }
- const char *infoname() const { return (m_current_info != nullptr) ? m_current_info->shortname() : "???"; }
+ const char *infoname() const { return (m_current_info != nullptr) ? m_current_info->shortname().c_str() : "???"; }
int line() const { return XML_GetCurrentLineNumber(m_parser); }
int column() const { return XML_GetCurrentColumnNumber(m_parser); }
const char *parser_error() const { return XML_ErrorString(XML_GetErrorCode(m_parser)); }
@@ -55,7 +55,8 @@ private:
void unknown_attribute(const char *attrname) { parse_error("Unknown attribute: %s", attrname); }
// internal helpers
- void parse_attributes(const char **attributes, int numattrs, const char *attrlist[], const char *outlist[]);
+ template <typename T> std::vector<std::string> parse_attributes(const char **attributes, const T &attrlist);
+ bool parse_name_and_value(const char **attributes, std::string &name, std::string &value);
void add_rom_entry(const char *name, const char *hashdata, UINT32 offset, UINT32 length, UINT32 flags);
// expat callbacks
@@ -91,10 +92,76 @@ private:
// device type definition
const device_type SOFTWARE_LIST = &device_creator<software_list_device>;
+false_software_list_loader false_software_list_loader::s_instance;
+rom_software_list_loader rom_software_list_loader::s_instance;
+image_software_list_loader image_software_list_loader::s_instance;
//**************************************************************************
+// SOFTWARE LIST LOADER
+//**************************************************************************
+
+//-------------------------------------------------
+// false_software_list_loader::load_software
+//-------------------------------------------------
+
+bool false_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
+{
+ return false;
+}
+
+
+//-------------------------------------------------
+// rom_software_list_loader::load_software
+//-------------------------------------------------
+
+bool rom_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
+{
+ swlist.machine().rom_load().load_software_part_region(device, swlist, swname, start_entry);
+ return true;
+}
+
+
+//-------------------------------------------------
+// image_software_list_loader::load_software
+//-------------------------------------------------
+
+bool image_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
+{
+ return device.load_software(swlist, swname, start_entry);
+}
+
+
+//**************************************************************************
+// FEATURE LIST ITEM
+//**************************************************************************
+
+//-------------------------------------------------
+// feature_list_item - constructor
+//-------------------------------------------------
+
+feature_list_item::feature_list_item(const std::string &name, const std::string &value)
+ : m_next(nullptr),
+ m_name(name),
+ m_value(value)
+{
+}
+
+
+//-------------------------------------------------
+// feature_list_item - constructor
+//-------------------------------------------------
+
+feature_list_item::feature_list_item(std::string &&name, std::string &&value)
+ : m_next(nullptr),
+ m_name(std::move(name)),
+ m_value(std::move(value))
+{
+}
+
+
+//**************************************************************************
// SOFTWARE PART
//**************************************************************************
@@ -102,15 +169,12 @@ const device_type SOFTWARE_LIST = &device_creator<software_list_device>;
// software_part - constructor
//-------------------------------------------------
-software_part::software_part(software_info &info, const char *name, const char *interface)
+software_part::software_part(software_info &info, std::string &&name, std::string &&interface)
: m_next(nullptr),
m_info(info),
- m_name(name),
- m_interface(interface)
+ m_name(std::move(name)),
+ m_interface(std::move(interface))
{
- // ensure strings we are passed are in the string pool
- assert(info.list().string_pool_contains(name));
- assert(info.list().string_pool_contains(interface));
}
@@ -119,14 +183,12 @@ software_part::software_part(software_info &info, const char *name, const char *
// feature, if specified
//-------------------------------------------------
-const char *software_part::feature(const char *feature_name) const
+const char *software_part::feature(const std::string &feature_name) const
{
- assert(feature_name != nullptr);
-
// scan the feature list for an entry matching feature_name and return the value
for (const feature_list_item &feature : m_featurelist)
- if (strcmp(feature.name(), feature_name) == 0)
- return feature.value();
+ if (feature.name() == feature_name)
+ return feature.value().c_str();
return nullptr;
}
@@ -190,7 +252,7 @@ software_compatibility software_part::is_compatible(const software_list_device &
bool software_part::matches_interface(const char *interface_list) const
{
// if we have no interface, then we match by default
- if (m_interface == nullptr)
+ if (m_interface.empty())
return true;
// copy the comma-delimited interface list and ensure it ends with a final comma
@@ -239,20 +301,13 @@ device_image_interface *software_part::find_mountable_image(const machine_config
// software_info - constructor
//-------------------------------------------------
-software_info::software_info(software_list_device &list, const char *name, const char *parent, const char *supported)
+software_info::software_info(software_list_device &list, std::string &&name, std::string &&parent, const char *supported)
: m_next(nullptr),
m_list(list),
m_supported(SOFTWARE_SUPPORTED_YES),
- m_shortname(name),
- m_longname(nullptr),
- m_parentname(parent),
- m_year(nullptr),
- m_publisher(nullptr)
+ m_shortname(std::move(name)),
+ m_parentname(std::move(parent))
{
- // ensure strings we are passed are in the string pool
- assert(list.string_pool_contains(name));
- assert(list.string_pool_contains(parent));
-
// handle the supported flag if provided
if (supported != nullptr)
{
@@ -275,11 +330,11 @@ const software_part *software_info::find_part(const char *partname, const char *
if (partname != nullptr && strlen(partname)==0) partname = nullptr;
if (partname == nullptr && interface == nullptr)
- return m_partdata.first();
+ return &m_partdata.front();
// look for the part by name and match against the interface if provided
for (const software_part &part : m_partdata)
- if (partname != nullptr && strcmp(partname, part.name()) == 0)
+ if (partname != nullptr && (partname == part.name()))
{
if (interface == nullptr || part.matches_interface(interface))
return &part;
@@ -301,7 +356,7 @@ bool software_info::has_multiple_parts(const char *interface) const
int count = 0;
// increment the count for each match and stop if we hit more than 1
- for (software_part &part : m_partdata)
+ for (const software_part &part : m_partdata)
if (part.matches_interface(interface))
if (++count > 1)
return true;
@@ -325,7 +380,7 @@ software_list_device::software_list_device(const machine_config &mconfig, const
m_filter(nullptr),
m_parsed(false),
m_file(mconfig.options().hash_path(), OPEN_FLAG_READ),
- m_description(nullptr)
+ m_description("")
{
}
@@ -386,12 +441,12 @@ void software_list_device::find_approx_matches(const char *name, int matches, co
// iterate over our info (will cause a parse if needed)
for (const software_info &swinfo : get_info())
{
- const software_part *part = swinfo.first_part();
- if ((interface == nullptr || part->matches_interface(interface)) && part->is_compatible(*this) == SOFTWARE_IS_COMPATIBLE)
+ const software_part &part = swinfo.parts().front();
+ if ((interface == nullptr || part.matches_interface(interface)) && part.is_compatible(*this) == SOFTWARE_IS_COMPATIBLE)
{
// pick the best match between driver name and description
- int longpenalty = driver_list::penalty_compare(name, swinfo.longname());
- int shortpenalty = driver_list::penalty_compare(name, swinfo.shortname());
+ int longpenalty = driver_list::penalty_compare(name, swinfo.longname().c_str());
+ int shortpenalty = driver_list::penalty_compare(name, swinfo.shortname().c_str());
int curpenalty = MIN(longpenalty, shortpenalty);
// insert into the sorted table of matches
@@ -423,10 +478,9 @@ void software_list_device::release()
{
osd_printf_verbose("Resetting %s\n", m_file.filename());
m_parsed = false;
- m_description = nullptr;
+ m_description.clear();
m_errors.clear();
- m_infolist.reset();
- m_stringpool.reset();
+ m_infolist.clear();
}
@@ -476,9 +530,11 @@ void software_list_device::display_matches(const machine_config &config, const c
osd_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlistdev.list_name(), swlistdev.description());
// print them out
- for (auto & matche : matches)
- if (matche != nullptr)
- osd_printf_error("%-18s%s\n", matche->shortname(), matche->longname());
+ for (auto &match : matches)
+ {
+ if (match != nullptr)
+ osd_printf_error("%-18s%s\n", match->shortname().c_str(), match->longname().c_str());
+ }
osd_printf_error("\n");
}
@@ -492,7 +548,7 @@ void software_list_device::display_matches(const machine_config &config, const c
// from an intermediate point
//-------------------------------------------------
-const software_info *software_list_device::find(const char *look_for, const software_info *prev)
+const software_info *software_list_device::find(const char *look_for)
{
// nullptr search returns nothing
if (look_for == nullptr)
@@ -501,11 +557,20 @@ const software_info *software_list_device::find(const char *look_for, const soft
bool iswild = strchr(look_for, '*') != nullptr || strchr(look_for, '?');
// find a match (will cause a parse if needed when calling get_info)
- for (prev = (prev != nullptr) ? prev->next() : get_info().first(); prev != nullptr; prev = prev->next())
- if ((iswild && core_strwildcmp(look_for, prev->shortname()) == 0) || core_stricmp(look_for, prev->shortname()) == 0)
- break;
-
- return prev;
+ const auto &info_list = get_info();
+ auto iter = std::find_if(
+ info_list.begin(),
+ info_list.end(),
+ [&](const software_info &info)
+ {
+ const char *shortname = info.shortname().c_str();
+ return (iswild && core_strwildcmp(look_for, shortname) == 0)
+ || core_stricmp(look_for, shortname) == 0;
+ });
+
+ return iter != info_list.end()
+ ? &*iter
+ : nullptr;
}
@@ -549,7 +614,7 @@ void software_list_device::device_validity_check(validity_checker &valid) const
{
// add to the global map whenever we check a list so we don't re-check
// it in the future
- if (valid.already_checked(std::string("softlist/").append(m_list_name.c_str()).c_str()))
+ if (valid.already_checked(std::string("softlist/").append(m_list_name).c_str()))
return;
// do device validation only in case of validate command
@@ -572,7 +637,7 @@ void software_list_device::internal_validity_check(validity_checker &valid)
softlist_map names;
softlist_map descriptions;
- for (software_info &swinfo : get_info())
+ for (const software_info &swinfo : get_info())
{
// first parse and output core errors if any
if (m_errors.length() > 0)
@@ -584,30 +649,30 @@ void software_list_device::internal_validity_check(validity_checker &valid)
// Now check if the xml data is valid:
// Did we lost any description?
- if (swinfo.longname() == nullptr)
+ if (swinfo.longname().empty())
{
- osd_printf_error("%s: %s has no description\n", filename(), swinfo.shortname());
+ osd_printf_error("%s: %s has no description\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost any year?
- if (swinfo.year() == nullptr)
+ if (swinfo.year().empty())
{
- osd_printf_error("%s: %s has no year\n", filename(), swinfo.shortname());
+ osd_printf_error("%s: %s has no year\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost any publisher?
- if (swinfo.publisher() == nullptr)
+ if (swinfo.publisher().empty())
{
- osd_printf_error("%s: %s has no publisher\n", filename(), swinfo.shortname());
+ osd_printf_error("%s: %s has no publisher\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost the software parts?
if (swinfo.parts().empty())
{
- osd_printf_error("%s: %s has no part\n", filename(), swinfo.shortname());
+ osd_printf_error("%s: %s has no part\n", filename(), swinfo.shortname().c_str());
break;
}
@@ -616,66 +681,66 @@ void software_list_device::internal_validity_check(validity_checker &valid)
// check for duplicate names
if (!names.insert(std::make_pair(swinfo.shortname(), &swinfo)).second)
{
- software_info *match = names.find(swinfo.shortname())->second;
- osd_printf_error("%s: %s is a duplicate name (%s)\n", filename(), swinfo.shortname(), match->shortname());
+ const software_info *match = names.find(swinfo.shortname())->second;
+ osd_printf_error("%s: %s is a duplicate name (%s)\n", filename(), swinfo.shortname().c_str(), match->shortname().c_str());
}
// check for duplicate descriptions
std::string longname = std::string(swinfo.longname());
if (!descriptions.insert(std::make_pair(strmakelower(longname), &swinfo)).second)
- osd_printf_error("%s: %s is a duplicate description (%s)\n", filename(), swinfo.longname(), swinfo.shortname());
+ osd_printf_error("%s: %s is a duplicate description (%s)\n", filename(), swinfo.longname().c_str(), swinfo.shortname().c_str());
bool is_clone = false;
- if (swinfo.parentname() != nullptr)
+ if (!swinfo.parentname().empty())
{
is_clone = true;
- if (strcmp(swinfo.parentname(), swinfo.shortname()) == 0)
+ if (swinfo.parentname() == swinfo.shortname())
{
- osd_printf_error("%s: %s is set as a clone of itself\n", filename(), swinfo.shortname());
+ osd_printf_error("%s: %s is set as a clone of itself\n", filename(), swinfo.shortname().c_str());
break;
}
// make sure the parent exists
- const software_info *swinfo2 = find(swinfo.parentname());
+ const software_info *swinfo2 = find(swinfo.parentname().c_str());
if (swinfo2 == nullptr)
- osd_printf_error("%s: parent '%s' software for '%s' not found\n", filename(), swinfo.parentname(), swinfo.shortname());
- else if (swinfo2->parentname() != nullptr)
- osd_printf_error("%s: %s is a clone of a clone\n", filename(), swinfo.shortname());
+ osd_printf_error("%s: parent '%s' software for '%s' not found\n", filename(), swinfo.parentname().c_str(), swinfo.shortname().c_str());
+ else if (!swinfo2->parentname().empty())
+ osd_printf_error("%s: %s is a clone of a clone\n", filename(), swinfo.shortname().c_str());
}
// make sure the driver name is 8 chars or less
- if ((is_clone && strlen(swinfo.shortname()) > NAME_LEN_CLONE) || (!is_clone && strlen(swinfo.shortname()) > NAME_LEN_PARENT))
- osd_printf_error("%s: %s %s driver name must be %d characters or less\n", filename(), swinfo.shortname(),
+ if ((is_clone && swinfo.shortname().length() > NAME_LEN_CLONE) || (!is_clone && swinfo.shortname().length() > NAME_LEN_PARENT))
+ osd_printf_error("%s: %s %s driver name must be %d characters or less\n", filename(), swinfo.shortname().c_str(),
is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
// make sure the year is only digits, '?' or '+'
- for (const char *s = swinfo.year(); *s != 0; s++)
+ for (const char *s = swinfo.year().c_str(); *s != 0; s++)
if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
{
- osd_printf_error("%s: %s has an invalid year '%s'\n", filename(), swinfo.shortname(), swinfo.year());
+ osd_printf_error("%s: %s has an invalid year '%s'\n", filename(), swinfo.shortname().c_str(), swinfo.year().c_str());
break;
}
softlist_map part_names;
- for (software_part &part : swinfo.parts())
+ for (const software_part &part : swinfo.parts())
{
- if (part.interface() == nullptr)
- osd_printf_error("%s: %s has a part (%s) without interface\n", filename(), swinfo.shortname(), part.name());
+ if (part.interface().empty())
+ osd_printf_error("%s: %s has a part (%s) without interface\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
if (part.romdata() == nullptr)
- osd_printf_error("%s: %s has a part (%s) with no data\n", filename(), swinfo.shortname(), part.name());
+ osd_printf_error("%s: %s has a part (%s) with no data\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
if (!part_names.insert(std::make_pair(part.name(), &swinfo)).second)
- osd_printf_error("%s: %s has a part (%s) whose name is duplicate\n", filename(), swinfo.shortname(), part.name());
+ osd_printf_error("%s: %s has a part (%s) whose name is duplicate\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
for (const rom_entry *data = part.romdata(); data->_name != nullptr; data++)
if (data->_hashdata != nullptr)
{
// make sure the hash is valid
- hash_collection hashes;
+ util::hash_collection hashes;
if (!hashes.from_internal_string(data->_hashdata))
- osd_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", filename(), swinfo.shortname(), data->_name, data->_hashdata);
+ osd_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", filename(), swinfo.shortname().c_str(), data->_name, data->_hashdata);
}
}
}
@@ -758,26 +823,67 @@ inline void softlist_parser::parse_error(Format &&fmt, Params &&... args)
// attributes into a list of strings
//-------------------------------------------------
-void softlist_parser::parse_attributes(const char **attributes, int numattrs, const char *attrlist[], const char *outlist[])
+template <typename T>
+std::vector<std::string> softlist_parser::parse_attributes(const char **attributes, const T &attrlist)
{
+ std::vector<std::string> outlist(std::distance(std::begin(attrlist), std::end(attrlist)));
+
// iterate over attribute/value pairs
for( ; attributes[0]; attributes += 2)
{
- int index;
+ auto iter = std::begin(attrlist);
// look for a match among the attributes provided
- for (index = 0; index < numattrs; index++)
- if (strcmp(attributes[0], attrlist[index]) == 0)
+ for (std::size_t index = 0; iter != std::end(attrlist); ++index, ++iter)
+ {
+ if (strcmp(attributes[0], *iter) == 0)
{
// if found, set the corresponding output entry to the value
outlist[index] = attributes[1];
break;
}
+ }
+
+ // if not found, report an unknown attribute
+ if (iter == std::end(attrlist))
+ unknown_attribute(attributes[0]);
+ }
+
+ return outlist;
+}
+
+
+//-------------------------------------------------
+// parse_name_and_value - helper to parse "name"
+// and "value" attribute pairs (allowing the
+// latter to be defined as an empty string)
+//-------------------------------------------------
+
+bool softlist_parser::parse_name_and_value(const char **attributes, std::string &name, std::string &value)
+{
+ bool found_value = false;
+
+ // iterate over attribute/value pairs
+ for( ; attributes[0]; attributes += 2)
+ {
+ // if found, set the corresponding output entry to the value
+ if (strcmp(attributes[0], "name") == 0)
+ {
+ name = attributes[1];
+ }
+
+ else if (strcmp(attributes[0], "value") == 0)
+ {
+ value = attributes[1];
+ found_value = true;
+ }
// if not found, report an unknown attribute
- if (index == numattrs)
+ else
unknown_attribute(attributes[0]);
}
+
+ return !name.empty() && found_value;
}
@@ -797,7 +903,7 @@ void softlist_parser::add_rom_entry(const char *name, const char *hashdata, UINT
// make sure we don't add duplicate regions
if (name != nullptr && (flags & ROMENTRY_TYPEMASK) == ROMENTRYTYPE_REGION)
- for (auto & elem : m_current_part->m_romdata)
+ for (auto &elem : m_current_part->m_romdata)
if (elem._name != nullptr && strcmp(elem._name, name) == 0)
parse_error("Duplicated dataarea %s in software %s", name, infoname());
@@ -920,11 +1026,10 @@ void softlist_parser::parse_root_start(const char *tagname, const char **attribu
if (strcmp(tagname, "softwarelist") == 0)
{
static const char *attrnames[] = { "name", "description" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ const auto attrvalues = parse_attributes(attributes, attrnames);
- if (attrvalues[1] != nullptr)
- m_list.m_description = m_list.add_string(attrvalues[1]);
+ if (!attrvalues[1].empty())
+ m_list.m_description = attrvalues[1];
}
else
unknown_tag(tagname);
@@ -942,11 +1047,13 @@ void softlist_parser::parse_main_start(const char *tagname, const char **attribu
if (strcmp(tagname, "software") == 0)
{
static const char *attrnames[] = { "name", "cloneof", "supported" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ auto attrvalues = parse_attributes(attributes, attrnames);
- if (attrvalues[0] != nullptr)
- m_current_info = &m_list.m_infolist.append(*global_alloc(software_info(m_list, m_list.add_string(attrvalues[0]), m_list.add_string(attrvalues[1]), attrvalues[2])));
+ if (!attrvalues[0].empty())
+ {
+ m_list.m_infolist.emplace_back(m_list, std::move(attrvalues[0]), std::move(attrvalues[1]), attrvalues[2].c_str());
+ m_current_info = &m_list.m_infolist.back();
+ }
else
parse_error("No name defined for item");
}
@@ -984,12 +1091,10 @@ void softlist_parser::parse_soft_start(const char *tagname, const char **attribu
// <info name='' value=''>
else if (strcmp(tagname, "info") == 0)
{
- static const char *attrnames[] = { "name", "value" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ std::string infoname, infovalue;
- if (attrvalues[0] != nullptr && attrvalues[1] != nullptr)
- m_current_info->m_other_info.append(*global_alloc(feature_list_item(m_list.add_string(attrvalues[0]), m_list.add_string(attrvalues[1]))));
+ if (parse_name_and_value(attributes, infoname, infovalue))
+ m_current_info->m_other_info.emplace_back(std::move(infoname), std::move(infovalue));
else
parse_error("Incomplete other_info definition");
}
@@ -997,12 +1102,10 @@ void softlist_parser::parse_soft_start(const char *tagname, const char **attribu
// <sharedfeat name='' value=''>
else if (strcmp(tagname, "sharedfeat") == 0)
{
- static const char *attrnames[] = { "name", "value" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ std::string featname, featvalue;
- if (attrvalues[0] != nullptr && attrvalues[1] != nullptr)
- m_current_info->m_shared_info.append(*global_alloc(feature_list_item(m_list.add_string(attrvalues[0]), m_list.add_string(attrvalues[1]))));
+ if (parse_name_and_value(attributes, featname, featvalue))
+ m_current_info->m_shared_info.emplace_back(std::move(featname), std::move(featvalue));
else
parse_error("Incomplete sharedfeat definition");
}
@@ -1011,11 +1114,13 @@ void softlist_parser::parse_soft_start(const char *tagname, const char **attribu
else if (strcmp(tagname, "part" ) == 0)
{
static const char *attrnames[] = { "name", "interface" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ auto attrvalues = parse_attributes(attributes, attrnames);
- if (attrvalues[0] != nullptr && attrvalues[1] != nullptr && strcmp(attrvalues[0], "") != 0 && strcmp(attrvalues[1], "") != 0)
- m_current_part = &m_current_info->m_partdata.append(*global_alloc(software_part(*m_current_info, m_list.add_string(attrvalues[0]), m_list.add_string(attrvalues[1]))));
+ if (!attrvalues[0].empty() && !attrvalues[1].empty())
+ {
+ m_current_info->m_partdata.emplace_back(*m_current_info, std::move(attrvalues[0]), std::move(attrvalues[1]));
+ m_current_part = &m_current_info->m_partdata.back();
+ }
else
parse_error("Incomplete part definition");
}
@@ -1042,40 +1147,39 @@ void softlist_parser::parse_part_start(const char *tagname, const char **attribu
if (strcmp(tagname, "dataarea") == 0)
{
static const char *attrnames[] = { "name", "size", "width", "endianness" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ const auto attrvalues = parse_attributes(attributes, attrnames);
- if (attrvalues[0] != nullptr && attrvalues[1] != nullptr && strcmp(attrvalues[0], "") != 0 && strcmp(attrvalues[1], "") != 0)
+ if (!attrvalues[0].empty() && !attrvalues[1].empty())
{
// handle region attributes
- const char *width = attrvalues[2];
- const char *endianness = attrvalues[3];
+ const std::string &width = attrvalues[2];
+ const std::string &endianness = attrvalues[3];
UINT32 regionflags = ROMENTRYTYPE_REGION;
- if (width != nullptr)
+ if (!width.empty())
{
- if (strcmp(width, "8") == 0)
+ if (width == "8")
regionflags |= ROMREGION_8BIT;
- else if (strcmp(width, "16") == 0)
+ else if (width == "16")
regionflags |= ROMREGION_16BIT;
- else if (strcmp(width, "32") == 0)
+ else if (width == "32")
regionflags |= ROMREGION_32BIT;
- else if (strcmp(width, "64") == 0)
+ else if (width == "64")
regionflags |= ROMREGION_64BIT;
else
parse_error("Invalid dataarea width");
}
- if (endianness != nullptr)
+ if (!endianness.empty())
{
- if (strcmp(endianness, "little") == 0)
+ if (endianness == "little")
regionflags |= ROMREGION_LE;
- else if (strcmp(endianness, "big") == 0)
+ else if (endianness == "big")
regionflags |= ROMREGION_BE;
else
parse_error("Invalid dataarea endianness");
}
- add_rom_entry(attrvalues[0], nullptr, 0, strtol(attrvalues[1], nullptr, 0), regionflags);
+ add_rom_entry(attrvalues[0].c_str(), nullptr, 0, strtol(attrvalues[1].c_str(), nullptr, 0), regionflags);
}
else
parse_error("Incomplete dataarea definition");
@@ -1085,11 +1189,10 @@ void softlist_parser::parse_part_start(const char *tagname, const char **attribu
else if (strcmp(tagname, "diskarea") == 0)
{
static const char *attrnames[] = { "name" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ const auto attrvalues = parse_attributes(attributes, attrnames);
- if (attrvalues[0] != nullptr)
- add_rom_entry(attrvalues[0], nullptr, 0, 1, ROMENTRYTYPE_REGION | ROMREGION_DATATYPEDISK);
+ if (!attrvalues[0].empty())
+ add_rom_entry(attrvalues[0].c_str(), nullptr, 0, 1, ROMENTRYTYPE_REGION | ROMREGION_DATATYPEDISK);
else
parse_error("Incomplete diskarea definition");
}
@@ -1097,12 +1200,10 @@ void softlist_parser::parse_part_start(const char *tagname, const char **attribu
// <feature name='' value=''>
else if (strcmp(tagname, "feature") == 0)
{
- static const char *attrnames[] = { "name", "value" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
+ std::string featname, featvalue;
- if (attrvalues[0] != nullptr)
- m_current_part->m_featurelist.append(*global_alloc(feature_list_item(m_list.add_string(attrvalues[0]), m_list.add_string(attrvalues[1]))));
+ if (parse_name_and_value(attributes, featname, featvalue))
+ m_current_part->m_featurelist.emplace_back(std::move(featname), std::move(featvalue));
else
parse_error("Incomplete feature definition");
}
@@ -1133,71 +1234,70 @@ void softlist_parser::parse_data_start(const char *tagname, const char **attribu
if (strcmp(tagname, "rom") == 0)
{
static const char *attrnames[] = { "name", "size", "crc", "sha1", "offset", "value", "status", "loadflag" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
-
- const char *name = attrvalues[0];
- const char *sizestr = attrvalues[1];
- const char *crc = attrvalues[2];
- const char *sha1 = attrvalues[3];
- const char *offsetstr = attrvalues[4];
- const char *value = attrvalues[5];
- const char *status = attrvalues[6];
- const char *loadflag = attrvalues[7];
- if (sizestr != nullptr && offsetstr != nullptr)
+ const auto attrvalues = parse_attributes(attributes, attrnames);
+
+ const std::string &name = attrvalues[0];
+ const std::string &sizestr = attrvalues[1];
+ const std::string &crc = attrvalues[2];
+ const std::string &sha1 = attrvalues[3];
+ const std::string &offsetstr = attrvalues[4];
+ const std::string &value = attrvalues[5];
+ const std::string &status = attrvalues[6];
+ const std::string &loadflag = attrvalues[7];
+ if (!sizestr.empty() && !offsetstr.empty())
{
- UINT32 length = strtol(sizestr, nullptr, 0);
- UINT32 offset = strtol(offsetstr, nullptr, 0);
+ UINT32 length = strtol(sizestr.c_str(), nullptr, 0);
+ UINT32 offset = strtol(offsetstr.c_str(), nullptr, 0);
- if (loadflag != nullptr && strcmp(loadflag, "reload") == 0)
+ if (loadflag == "reload")
add_rom_entry(nullptr, nullptr, offset, length, ROMENTRYTYPE_RELOAD | ROM_INHERITFLAGS);
- else if (loadflag != nullptr && strcmp(loadflag, "reload_plain") == 0)
+ else if (loadflag == "reload_plain")
add_rom_entry(nullptr, nullptr, offset, length, ROMENTRYTYPE_RELOAD);
- else if (loadflag != nullptr && strcmp(loadflag, "continue") == 0)
+ else if (loadflag == "continue")
add_rom_entry(nullptr, nullptr, offset, length, ROMENTRYTYPE_CONTINUE | ROM_INHERITFLAGS);
- else if (loadflag != nullptr && strcmp(loadflag, "fill") == 0)
- add_rom_entry(nullptr, (const char *)(FPTR)(strtol(value, nullptr, 0) & 0xff), offset, length, ROMENTRYTYPE_FILL);
- else if (name != nullptr)
+ else if (loadflag == "fill")
+ add_rom_entry(nullptr, (const char *)(FPTR)(strtol(value.c_str(), nullptr, 0) & 0xff), offset, length, ROMENTRYTYPE_FILL);
+ else if (!name.empty())
{
- bool baddump = (status != nullptr && strcmp(status, "baddump") == 0);
- bool nodump = (status != nullptr && strcmp(status, "nodump") == 0);
+ bool baddump = (status == "baddump");
+ bool nodump = (status == "nodump");
std::string hashdata;
if (nodump)
{
hashdata = string_format("%s", NO_DUMP);
- if (crc != nullptr && sha1 != nullptr)
+ if (!crc.empty() && !sha1.empty())
parse_error("No need for hash definition");
}
else
{
- if (crc != nullptr && sha1 != nullptr)
- hashdata = string_format("%c%s%c%s%s", hash_collection::HASH_CRC, crc, hash_collection::HASH_SHA1, sha1, (baddump ? BAD_DUMP : ""));
+ if (!crc.empty() && !sha1.empty())
+ hashdata = string_format("%c%s%c%s%s", util::hash_collection::HASH_CRC, crc, util::hash_collection::HASH_SHA1, sha1, (baddump ? BAD_DUMP : ""));
else
parse_error("Incomplete rom hash definition");
}
// Handle loadflag attribute
int romflags = 0;
- if (loadflag != nullptr && strcmp(loadflag, "load16_word_swap") == 0)
+ if (loadflag == "load16_word_swap")
romflags = ROM_GROUPWORD | ROM_REVERSE;
- else if (loadflag != nullptr && strcmp(loadflag, "load16_byte") == 0)
+ else if (loadflag == "load16_byte")
romflags = ROM_SKIP(1);
- else if (loadflag != nullptr && strcmp(loadflag, "load32_word_swap") == 0)
+ else if (loadflag == "load32_word_swap")
romflags = ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2);
- else if (loadflag != nullptr && strcmp(loadflag, "load32_word") == 0)
+ else if (loadflag == "load32_word")
romflags = ROM_GROUPWORD | ROM_SKIP(2);
- else if (loadflag != nullptr && strcmp(loadflag, "load32_byte") == 0)
+ else if (loadflag == "load32_byte")
romflags = ROM_SKIP(3);
- add_rom_entry(name, hashdata.c_str(), offset, length, ROMENTRYTYPE_ROM | romflags);
+ add_rom_entry(name.c_str(), hashdata.c_str(), offset, length, ROMENTRYTYPE_ROM | romflags);
}
else
parse_error("Rom name missing");
}
- else if (sizestr != nullptr && loadflag != nullptr && strcmp(loadflag, "ignore") == 0)
+ else if (!sizestr.empty() && !loadflag.empty() && loadflag == "ignore")
{
- UINT32 length = strtol(sizestr, nullptr, 0);
+ UINT32 length = strtol(sizestr.c_str(), nullptr, 0);
add_rom_entry(nullptr, nullptr, 0, length, ROMENTRYTYPE_IGNORE | ROM_INHERITFLAGS);
}
else
@@ -1208,23 +1308,22 @@ void softlist_parser::parse_data_start(const char *tagname, const char **attribu
else if (strcmp(tagname, "disk") == 0)
{
static const char *attrnames[] = { "name", "sha1", "status", "writeable" };
- const char *attrvalues[ARRAY_LENGTH(attrnames)] = { nullptr };
- parse_attributes(attributes, ARRAY_LENGTH(attrnames), attrnames, attrvalues);
-
- const char *name = attrvalues[0];
- const char *sha1 = attrvalues[1];
- const char *status = attrvalues[2];
- const char *writeablestr = attrvalues[3];
- if (name != nullptr && sha1 != nullptr)
+ const auto attrvalues = parse_attributes(attributes, attrnames);
+
+ const std::string &name = attrvalues[0];
+ const std::string &sha1 = attrvalues[1];
+ const std::string &status = attrvalues[2];
+ const std::string &writeablestr = attrvalues[3];
+ if (!name.empty() && !sha1.empty())
{
- bool baddump = (status != nullptr && strcmp(status, "baddump") == 0);
- bool nodump = (status != nullptr && strcmp(status, "nodump" ) == 0);
- bool writeable = (writeablestr != nullptr && strcmp(writeablestr, "yes") == 0);
- std::string hashdata = string_format("%c%s%s", hash_collection::HASH_SHA1, sha1, (nodump ? NO_DUMP : (baddump ? BAD_DUMP : "")));
+ const bool baddump = (status == "baddump");
+ const bool nodump = (status == "nodump" );
+ const bool writeable = (writeablestr == "yes");
+ std::string hashdata = string_format("%c%s%s", util::hash_collection::HASH_SHA1, sha1, (nodump ? NO_DUMP : (baddump ? BAD_DUMP : "")));
- add_rom_entry(name, hashdata.c_str(), 0, 0, ROMENTRYTYPE_ROM | (writeable ? DISK_READWRITE : DISK_READONLY));
+ add_rom_entry(name.c_str(), hashdata.c_str(), 0, 0, ROMENTRYTYPE_ROM | (writeable ? DISK_READWRITE : DISK_READONLY));
}
- else if (status == nullptr || !strcmp(status, "nodump")) // a no_dump chd is not an incomplete entry
+ else if (status.empty() || (status == "nodump")) // a no_dump chd is not an incomplete entry
parse_error("Incomplete disk definition");
}
@@ -1247,15 +1346,15 @@ void softlist_parser::parse_soft_end(const char *tagname)
// <description>
if (strcmp(tagname, "description") == 0)
- m_current_info->m_longname = m_list.add_string(m_data_accum.c_str());
+ m_current_info->m_longname = m_data_accum;
// <year>
else if (strcmp(tagname, "year") == 0)
- m_current_info->m_year = m_list.add_string(m_data_accum.c_str());
+ m_current_info->m_year = m_data_accum;
// <publisher>
else if (strcmp(tagname, "publisher") == 0)
- m_current_info->m_publisher = m_list.add_string(m_data_accum.c_str());
+ m_current_info->m_publisher = m_data_accum;
// </part>
else if (strcmp(tagname, "part") == 0)
@@ -1272,7 +1371,7 @@ void softlist_parser::parse_soft_end(const char *tagname)
// get the info; if present, copy shared data (we assume name/value strings live
// in the string pool and don't need to be reallocated)
if (m_current_info != nullptr)
- for (feature_list_item &item : m_current_info->shared_info())
- m_current_part->m_featurelist.append(*global_alloc(feature_list_item(item.name(), item.value())));
+ for (const feature_list_item &item : m_current_info->shared_info())
+ m_current_part->m_featurelist.emplace_back(item.name(), item.value());
}
}