From 54279dbf114090e67ff391fce878a9c2d3af466f Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 25 Mar 2016 15:25:30 +1100 Subject: [PATCH] Make emu_file archive searh order CRC+path, CRC+partial path, CRC, path, partial path and fold some redundant code --- .gitignore | 2 +- src/emu/fileio.cpp | 104 ++++++++--------------------------------- src/emu/fileio.h | 1 - src/lib/util/un7z.cpp | 56 +++++++++++++++++----- src/lib/util/unzip.cpp | 40 ++++++++++------ src/lib/util/unzip.h | 4 +- 6 files changed, 94 insertions(+), 113 deletions(-) diff --git a/.gitignore b/.gitignore index abbcbee172e..083e0369858 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *~ .*.sw? +*.mo *.pyc *.pyo .DS_Store @@ -36,7 +37,6 @@ /.idea regtests/chdman/temp regtests/jedutil/output -*.mo /CMakeLists.txt /src/devices/cpu/m68000/m68kops.cpp /src/devices/cpu/m68000/m68kops.h diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index 812f2a7007f..fec82d9e592 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -334,17 +334,9 @@ osd_file::error emu_file::open_next() // if we're opening for read-only we have other options if ((m_openflags & (OPEN_FLAG_READ | OPEN_FLAG_WRITE)) == OPEN_FLAG_READ) { - std::string tempfullpath = m_fullpath; - filerr = attempt_zipped(); if (filerr == osd_file::error::NONE) break; - - m_fullpath = tempfullpath; - - filerr = attempt__7zped(); - if (filerr == osd_file::error::NONE) - break; } } return filerr; @@ -640,13 +632,12 @@ osd_file::error emu_file::attempt_zipped() while (1) { // find the final path separator - int dirsep = m_fullpath.find_last_of(PATH_SEPARATOR[0]); - if (dirsep == -1) + auto const dirsep = m_fullpath.find_last_of(PATH_SEPARATOR[0]); + if (dirsep == std::string::npos) return osd_file::error::NOT_FOUND; - if (restrict_to_mediapath()) - if ( !part_of_mediapath(m_fullpath) ) - return osd_file::error::NOT_FOUND; + if (restrict_to_mediapath() && !part_of_mediapath(m_fullpath)) + return osd_file::error::NOT_FOUND; // insert the part from the right of the separator into the head of the filename if (filename.length() > 0) @@ -654,13 +645,22 @@ osd_file::error emu_file::attempt_zipped() filename.insert(0, m_fullpath.substr(dirsep + 1, -1)); // remove this part of the filename and append a .zip extension - m_fullpath = m_fullpath.substr(0, dirsep).append(".zip"); + m_fullpath = m_fullpath.substr(0, dirsep).append(".zip"); // attempt to open the ZIP file util::archive_file::ptr zip; util::archive_file::error ziperr = util::archive_file::open_zip(m_fullpath, zip); - // chop the .zip back off the filename before continuing + if (ziperr != util::archive_file::error::NONE) + { + // remove this part of the filename and append a .7z extension + m_fullpath = m_fullpath.substr(0, dirsep).append(".7z"); + + // attempt to open the 7zip file + ziperr = util::archive_file::open_7z(m_fullpath, zip); + } + + // chop the .zip/.7z back off the filename before continuing m_fullpath = m_fullpath.substr(0, dirsep); // if we failed to open this file, continue scanning @@ -670,14 +670,16 @@ osd_file::error emu_file::attempt_zipped() int header = -1; // see if we can find a file with the right name and (if available) crc - if (m_openflags & OPEN_FLAG_HAS_CRC) header = zip->search(m_crc, filename); + if (m_openflags & OPEN_FLAG_HAS_CRC) header = zip->search(m_crc, filename, false); + if (header < 0 && (m_openflags & OPEN_FLAG_HAS_CRC)) header = zip->search(m_crc, filename, true); // if that failed, look for a file with the right crc, but the wrong filename if (header < 0 && (m_openflags & OPEN_FLAG_HAS_CRC)) header = zip->search(m_crc); // if that failed, look for a file with the right name; reporting a bad checksum // is more helpful and less confusing than reporting "rom not found" - if (header < 0) header = zip->search(filename); + if (header < 0) header = zip->search(filename, false); + if (header < 0) header = zip->search(filename, true); // if we got it, read the data if (header >= 0) @@ -697,74 +699,6 @@ osd_file::error emu_file::attempt_zipped() } -//------------------------------------------------- -// attempt__7zped - attempt to open a .7z file -//------------------------------------------------- - -osd_file::error emu_file::attempt__7zped() -{ - std::string filename; - - // loop over directory parts up to the start of filename - while (1) - { - // find the final path separator - int dirsep = m_fullpath.find_last_of(PATH_SEPARATOR[0]); - if (dirsep == -1) - return osd_file::error::NOT_FOUND; - - if (restrict_to_mediapath()) - if ( !part_of_mediapath(m_fullpath) ) - return osd_file::error::NOT_FOUND; - - // insert the part from the right of the separator into the head of the filename - if (filename.length() > 0) - filename.insert(0, "/"); - filename.insert(0, m_fullpath.substr(dirsep + 1, -1)); - - // remove this part of the filename and append a .7z extension - m_fullpath = m_fullpath.substr(0, dirsep).append(".7z"); - - // attempt to open the _7Z file - util::archive_file::ptr _7z; - util::archive_file::error _7zerr = util::archive_file::open_7z(m_fullpath, _7z); - - // chop the ._7z back off the filename before continuing - m_fullpath = m_fullpath.substr(0, dirsep); - - // if we failed to open this file, continue scanning - if (_7zerr != util::archive_file::error::NONE) - continue; - - int fileno = -1; - - // see if we can find a file with the right name and (if available) crc - if (m_openflags & OPEN_FLAG_HAS_CRC) fileno = _7z->search(m_crc, filename); - - // if that failed, look for a file with the right crc, but the wrong filename - if ((fileno < 0) && (m_openflags & OPEN_FLAG_HAS_CRC)) fileno = _7z->search(m_crc); - - // if that failed, look for a file with the right name; reporting a bad checksum - // is more helpful and less confusing than reporting "rom not found" - if (fileno < 0) fileno = _7z->search(filename); - - if (fileno >= 0) - { - m_zipfile = std::move(_7z); - m_ziplength = m_zipfile->current_uncompressed_length(); - - // build a hash with just the CRC - m_hashes.reset(); - m_hashes.add_crc(m_zipfile->current_crc()); - return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? osd_file::error::NONE : load_zipped_file(); - } - - // close up the _7Z file and try the next level - _7z.reset(); - } -} - - //------------------------------------------------- // load_zipped_file - load a ZIPped file //------------------------------------------------- diff --git a/src/emu/fileio.h b/src/emu/fileio.h index a29372f071d..e71934ea22a 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -145,7 +145,6 @@ private: // internal helpers osd_file::error attempt_zipped(); - osd_file::error attempt__7zped(); osd_file::error load_zipped_file(); // internal state diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp index bca825c1f71..d4761c5347d 100644 --- a/src/lib/util/un7z.cpp +++ b/src/lib/util/un7z.cpp @@ -124,12 +124,21 @@ public: archive_file::error initialize(); - int first_file() { return search(0, 0, std::string(), false, false); } - int next_file() { return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string(), false, false); } + int first_file() { return search(0, 0, std::string(), false, false, false); } + int next_file() { return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string(), false, false, false); } - int search(std::uint32_t crc) { return search(0, crc, std::string(), true, false); } - int search(const std::string &filename) { return search(0, 0, filename, false, true); } - int search(std::uint32_t crc, const std::string &filename) { return search(0, crc, filename, true, true); } + int search(std::uint32_t crc) + { + return search(0, crc, std::string(), true, false, false); + } + int search(const std::string &filename, bool partialpath) + { + return search(0, 0, filename, false, true, partialpath); + } + int search(std::uint32_t crc, const std::string &filename, bool partialpath) + { + return search(0, crc, filename, true, true, partialpath); + } bool current_is_directory() const { return m_curr_is_dir; } const std::string ¤t_name() const { return m_curr_name; } @@ -144,7 +153,13 @@ private: m7z_file_impl &operator=(const m7z_file_impl &) = delete; m7z_file_impl &operator=(m7z_file_impl &&) = delete; - int search(int i, std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname); + int search( + int i, + std::uint32_t search_crc, + const std::string &search_filename, + bool matchcrc, + bool matchname, + bool partialpath); void make_utf8_name(int index); static constexpr std::size_t CACHE_SIZE = 8; @@ -187,9 +202,18 @@ public: virtual int first_file() override { return m_impl->first_file(); } virtual int next_file() override { return m_impl->next_file(); } - virtual int search(std::uint32_t crc) override { return m_impl->search(crc); } - virtual int search(const std::string &filename) override { return m_impl->search(filename); } - virtual int search(std::uint32_t crc, const std::string &filename) override { return m_impl->search(crc, filename); } + virtual int search(std::uint32_t crc) override + { + return m_impl->search(crc); + } + virtual int search(const std::string &filename, bool partialpath) override + { + return m_impl->search(filename, partialpath); + } + virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) override + { + return m_impl->search(crc, filename, partialpath); + } virtual bool current_is_directory() const override { return m_impl->current_is_directory(); } virtual const std::string ¤t_name() const override { return m_impl->current_name(); } @@ -373,7 +397,13 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length } -int m7z_file_impl::search(int i, std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname) +int m7z_file_impl::search( + int i, + std::uint32_t search_crc, + const std::string &search_filename, + bool matchcrc, + bool matchname, + bool partialpath) { for ( ; i < m_db.db.NumFiles; i++) { @@ -383,7 +413,11 @@ int m7z_file_impl::search(int i, std::uint32_t search_crc, const std::string &se const std::uint64_t size(f.Size); const std::uint32_t crc(f.Crc); const bool crcmatch(crc == search_crc); - const bool namematch(!core_stricmp(search_filename.c_str(), &m_utf8_buf[0])); + auto const partialoffset(m_utf8_buf.size() - 1 - search_filename.length()); + bool const partialpossible((m_utf8_buf.size() > (search_filename.length() + 1)) && (m_utf8_buf[partialoffset - 1] == '/')); + const bool namematch( + !core_stricmp(search_filename.c_str(), &m_utf8_buf[0]) || + (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), &m_utf8_buf[partialoffset]))); const bool found = ((!matchcrc && !matchname) || !f.IsDir) && (!matchcrc || crcmatch) && (!matchname || namematch); if (found) diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp index 2751f83ffb6..6a9e407252d 100644 --- a/src/lib/util/unzip.cpp +++ b/src/lib/util/unzip.cpp @@ -156,26 +156,27 @@ public: int first_file() { m_cd_pos = 0; - return search(0, std::string(), false, false); + return search(0, std::string(), false, false, false); } int next_file() { - return search(0, std::string(), false, false); + return search(0, std::string(), false, false, false); } + int search(std::uint32_t crc) { m_cd_pos = 0; - return search(crc, std::string(), true, false); + return search(crc, std::string(), true, false, false); } - int search(const std::string &filename) + int search(const std::string &filename, bool partialpath) { m_cd_pos = 0; - return search(0, filename, false, true); + return search(0, filename, false, true, partialpath); } - int search(std::uint32_t crc, const std::string &filename) + int search(std::uint32_t crc, const std::string &filename, bool partialpath) { m_cd_pos = 0; - return search(crc, filename, true, true); + return search(crc, filename, true, true, partialpath); } bool current_is_directory() const { return m_curr_is_dir; } @@ -191,7 +192,7 @@ private: zip_file_impl &operator=(const zip_file_impl &) = delete; zip_file_impl &operator=(zip_file_impl &&) = delete; - int search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname); + int search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath); archive_file::error reopen() { @@ -281,9 +282,18 @@ public: virtual int first_file() override { return m_impl->first_file(); } virtual int next_file() override { return m_impl->next_file(); } - virtual int search(std::uint32_t crc) override { return m_impl->search(crc); } - virtual int search(const std::string &filename) override { return m_impl->search(filename); } - virtual int search(std::uint32_t crc, const std::string &filename) override { return m_impl->search(crc, filename); } + virtual int search(std::uint32_t crc) override + { + return m_impl->search(crc); + } + virtual int search(const std::string &filename, bool partialpath) override + { + return m_impl->search(filename, partialpath); + } + virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) override + { + return m_impl->search(crc, filename, partialpath); + } virtual bool current_is_directory() const override { return m_impl->current_is_directory(); } virtual const std::string ¤t_name() const override { return m_impl->current_name(); } @@ -396,7 +406,7 @@ void zip_file_impl::close(ptr &&zip) in the ZIP -------------------------------------------------*/ -int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname) +int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath) { // if we're at or past the end, we're done std::string filename; @@ -437,7 +447,11 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi // check to see if it matches query bool const crcmatch(search_crc == m_header.crc); - const bool namematch(!core_stricmp(search_filename.c_str(), filename.c_str())); + auto const partialoffset(filename.length() - search_filename.length()); + bool const partialpossible((filename.length() > search_filename.length()) && (filename[partialoffset - 1] == '/')); + const bool namematch( + !core_stricmp(search_filename.c_str(), filename.c_str()) || + (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), filename.c_str() + partialoffset))); bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch); if (found) diff --git a/src/lib/util/unzip.h b/src/lib/util/unzip.h index 5fafaec57a4..928e6ef56d5 100644 --- a/src/lib/util/unzip.h +++ b/src/lib/util/unzip.h @@ -71,8 +71,8 @@ public: // find a file index by crc, filename or both - returns non-negative on match virtual int search(std::uint32_t crc) = 0; - virtual int search(const std::string &filename) = 0; - virtual int search(std::uint32_t crc, const std::string &filename) = 0; + virtual int search(const std::string &filename, bool partialpath) = 0; + virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) = 0; // information on most recently found file virtual bool current_is_directory() const = 0;