diff options
Diffstat (limited to 'src/emu/softlist.cpp')
-rw-r--r-- | src/emu/softlist.cpp | 455 |
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 ∂ @@ -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()); } } |