summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2016-03-18 19:22:43 +1100
committer Vas Crabb <vas@vastheman.com>2016-03-18 19:32:10 +1100
commit100fa28671af455853a6de1b2d7a3499fa6e185c (patch)
treee1d89e396fc7bc33b5c3b7b075f8138f9396ce3f /src/lib
parentacb27808d4f00b09958e5898966d7917b1debf1a (diff)
* Remove confusing method from vectorstreams that hide base_ios method (fixes disassembly view)
* Allow std::string to pass through core_file unmolested (reduces temporary allocations) * Make zip/7z instances of same class with uniform interface * zippath browsing is broken at the moment This is another step towards transparent archive support. It's now possible to access zip and 7z archives with the same code. Nothing is taking advantage of it yet. There's now some very similar code in fileio.cpp and clifront.cpp that could be folded at some point.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/util/cdrom.cpp2
-rw-r--r--src/lib/util/corefile.cpp6
-rw-r--r--src/lib/util/corefile.h6
-rw-r--r--src/lib/util/un7z.cpp79
-rw-r--r--src/lib/util/un7z.h83
-rw-r--r--src/lib/util/unzip.cpp362
-rw-r--r--src/lib/util/unzip.h64
-rw-r--r--src/lib/util/vecstream.h9
-rw-r--r--src/lib/util/zippath.cpp103
-rw-r--r--src/lib/util/zippath.h9
10 files changed, 332 insertions, 391 deletions
diff --git a/src/lib/util/cdrom.cpp b/src/lib/util/cdrom.cpp
index bd48a73d8d8..da3d921ae4a 100644
--- a/src/lib/util/cdrom.cpp
+++ b/src/lib/util/cdrom.cpp
@@ -244,7 +244,7 @@ cdrom_file *cdrom_open(const char *inputfile)
for (i = 0; i < file->cdtoc.numtrks; i++)
{
- osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname.c_str(), OPEN_FLAG_READ, file->fhandle[i]);
+ osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname, OPEN_FLAG_READ, file->fhandle[i]);
if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Unable to open file: %s\n", file->track_info.track[i].fname.c_str());
diff --git a/src/lib/util/corefile.cpp b/src/lib/util/corefile.cpp
index 5c16d886fe3..e3d34ec3738 100644
--- a/src/lib/util/corefile.cpp
+++ b/src/lib/util/corefile.cpp
@@ -1084,7 +1084,7 @@ osd_file::error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64
return an error code
-------------------------------------------------*/
-osd_file::error core_file::open(char const *filename, std::uint32_t openflags, ptr &file)
+osd_file::error core_file::open(std::string const &filename, std::uint32_t openflags, ptr &file)
{
try
{
@@ -1190,7 +1190,7 @@ core_file::~core_file()
pointer
-------------------------------------------------*/
-osd_file::error core_file::load(char const *filename, void **data, std::uint32_t &length)
+osd_file::error core_file::load(std::string const &filename, void **data, std::uint32_t &length)
{
ptr file;
@@ -1219,7 +1219,7 @@ osd_file::error core_file::load(char const *filename, void **data, std::uint32_t
return osd_file::error::NONE;
}
-osd_file::error core_file::load(char const *filename, dynamic_buffer &data)
+osd_file::error core_file::load(std::string const &filename, dynamic_buffer &data)
{
ptr file;
diff --git a/src/lib/util/corefile.h b/src/lib/util/corefile.h
index e66545440c2..8f71832411f 100644
--- a/src/lib/util/corefile.h
+++ b/src/lib/util/corefile.h
@@ -48,7 +48,7 @@ public:
// ----- file open/close -----
// open a file with the specified filename
- static osd_file::error open(const char *filename, std::uint32_t openflags, ptr &file);
+ static osd_file::error open(std::string const &filename, std::uint32_t openflags, ptr &file);
// open a RAM-based "file" using the given data and length (read-only)
static osd_file::error open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
@@ -100,8 +100,8 @@ public:
virtual const void *buffer() = 0;
// open a file with the specified filename, read it into memory, and return a pointer
- static osd_file::error load(const char *filename, void **data, std::uint32_t &length);
- static osd_file::error load(const char *filename, dynamic_buffer &data);
+ static osd_file::error load(std::string const &filename, void **data, std::uint32_t &length);
+ static osd_file::error load(std::string const &filename, dynamic_buffer &data);
// ----- file write -----
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp
index b05e4623e57..8b73faed49b 100644
--- a/src/lib/util/un7z.cpp
+++ b/src/lib/util/un7z.cpp
@@ -10,7 +10,7 @@
// this is based on unzip.c, with modifications needed to use the 7zip library
-#include "un7z.h"
+#include "unzip.h"
#include "corestr.h"
#include "unicode.h"
@@ -19,6 +19,7 @@
#include "lzma/C/7zCrc.h"
#include "lzma/C/7zVersion.h"
+#include <algorithm>
#include <array>
#include <cassert>
#include <cstdio>
@@ -28,6 +29,7 @@
#include <vector>
+namespace util {
namespace {
/***************************************************************************
TYPE DEFINITIONS
@@ -98,6 +100,7 @@ public:
static ptr find_cached(const std::string &filename)
{
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++)
{
// if we have a valid entry and it matches our filename, use it and remove from the cache
@@ -114,10 +117,11 @@ public:
static void cache_clear()
{
// clear call cache entries
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { }
}
- _7z_file::error initialize();
+ 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); }
@@ -126,11 +130,12 @@ public:
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); }
+ bool current_is_directory() const { return m_curr_is_dir; }
const std::string &current_name() const { return m_curr_name; }
std::uint64_t current_uncompressed_length() const { return m_curr_length; }
std::uint32_t current_crc() const { return m_curr_crc; }
- _7z_file::error decompress(void *buffer, std::uint32_t length);
+ archive_file::error decompress(void *buffer, std::uint32_t length);
private:
m7z_file_impl(const m7z_file_impl &) = delete;
@@ -143,10 +148,12 @@ private:
static constexpr std::size_t CACHE_SIZE = 8;
static std::array<ptr, CACHE_SIZE> s_cache;
+ static std::mutex s_cache_mutex;
const std::string m_filename; // copy of _7Z filename (for caching)
int m_curr_file_idx; // current file index
+ bool m_curr_is_dir; // current file is directory
std::string m_curr_name; // current file name
std::uint64_t m_curr_length; // current file uncompressed length
std::uint32_t m_curr_crc; // current file crc
@@ -170,7 +177,7 @@ private:
};
-class m7z_file_wrapper : public _7z_file
+class m7z_file_wrapper : public archive_file
{
public:
m7z_file_wrapper(m7z_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); }
@@ -183,6 +190,7 @@ public:
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 bool current_is_directory() const override { return m_impl->current_is_directory(); }
virtual const std::string &current_name() const override { return m_impl->current_name(); }
virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); }
virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); }
@@ -200,6 +208,7 @@ private:
***************************************************************************/
std::array<m7z_file_impl::ptr, m7z_file_impl::CACHE_SIZE> m7z_file_impl::s_cache;
+std::mutex m7z_file_impl::s_cache_mutex;
@@ -250,6 +259,7 @@ CFileInStream::CFileInStream()
m7z_file_impl::m7z_file_impl(const std::string &filename)
: m_filename(filename)
, m_curr_file_idx(-1)
+ , m_curr_is_dir(false)
, m_curr_name()
, m_curr_length(0)
, m_curr_crc(0)
@@ -269,11 +279,11 @@ m7z_file_impl::m7z_file_impl(const std::string &filename)
}
-_7z_file::error m7z_file_impl::initialize()
+archive_file::error m7z_file_impl::initialize()
{
osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length);
if (err != osd_file::error::NONE)
- return _7z_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
LookToRead_CreateVTable(&m_look_stream, False);
m_look_stream.realStream = &m_archive_stream;
@@ -286,9 +296,9 @@ _7z_file::error m7z_file_impl::initialize()
SRes const res = SzArEx_Open(&m_db, &m_look_stream.s, &m_alloc_imp, &m_alloc_temp_imp);
if (res != SZ_OK)
- return _7z_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
- return _7z_file::error::NONE;
+ return archive_file::error::NONE;
}
@@ -305,6 +315,7 @@ void m7z_file_impl::close(ptr &&archive)
archive->m_archive_stream.osdfile.reset();
// find the first NULL entry in the cache
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
std::size_t cachenum;
for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
if (!s_cache[cachenum])
@@ -331,7 +342,7 @@ void m7z_file_impl::close(ptr &&archive)
from a _7Z into the target buffer
-------------------------------------------------*/
-_7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
+archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
{
// make sure the file is open..
if (!m_archive_stream.osdfile)
@@ -339,7 +350,7 @@ _7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
m_archive_stream.currfpos = 0;
osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length);
if (err != osd_file::error::NONE)
- return _7z_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
}
size_t offset = 0;
@@ -353,11 +364,11 @@ _7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
&m_alloc_imp, &m_alloc_temp_imp);
if (res != SZ_OK)
- return _7z_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
std::memcpy(buffer, m_out_buffer + offset, length);
- return _7z_file::error::NONE;
+ return archive_file::error::NONE;
}
@@ -367,25 +378,22 @@ int m7z_file_impl::search(int i, std::uint32_t search_crc, const std::string &se
{
const CSzFileItem &f(m_db.db.Files[i]);
- // if it's a directory entry we don't care about it..
- if (!f.IsDir)
+ make_utf8_name(i);
+ 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]));
+
+ const bool found = ((!matchcrc && !matchname) || !f.IsDir) && (!matchcrc || crcmatch) && (!matchname || namematch);
+ if (found)
{
- make_utf8_name(i);
- 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]) == 0);
-
- const bool found = (!matchcrc || crcmatch) && (!matchname || namematch);
- if (found)
- {
- m_curr_file_idx = i;
- m_curr_name = &m_utf8_buf[0];
- m_curr_length = size;
- m_curr_crc = crc;
+ m_curr_file_idx = i;
+ m_curr_is_dir = bool(f.IsDir);
+ m_curr_name = &m_utf8_buf[0];
+ m_curr_length = size;
+ m_curr_crc = crc;
- return i;
- }
+ return i;
}
}
@@ -432,17 +440,13 @@ void m7z_file_impl::make_utf8_name(int index)
assert(out_pos < m_utf8_buf.size());
}
m_utf8_buf[out_pos++] = '\0';
+ m_utf8_buf.resize(out_pos);
}
} // anonymous namespace
-_7z_file::~_7z_file()
-{
-}
-
-
-_7z_file::error _7z_file::open(const std::string &filename, ptr &result)
+archive_file::error archive_file::open_7z(const std::string &filename, ptr &result)
{
// ensure we start with a NULL result
result.reset();
@@ -477,7 +481,10 @@ _7z_file::error _7z_file::open(const std::string &filename, ptr &result)
cache and free all memory
-------------------------------------------------*/
-void _7z_file::cache_clear()
+void m7z_file_cache_clear()
{
+ // This is a trampoline called from unzip.cpp to avoid the need to have the zip and 7zip code in one file
m7z_file_impl::cache_clear();
}
+
+} // namespace util
diff --git a/src/lib/util/un7z.h b/src/lib/util/un7z.h
deleted file mode 100644
index d2d2e18e25f..00000000000
--- a/src/lib/util/un7z.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles, Vas Crabb
-/***************************************************************************
-
- un7z.h
-
- 7z file management.
-
-***************************************************************************/
-
-// this is based on unzip.h, with modifications needed to use the 7zip library
-
-#pragma once
-
-#ifndef MAME_LIB_UTIL_UN7Z_H
-#define MAME_LIB_UTIL_UN7Z_H
-
-#include "osdcore.h"
-
-#include <cstdint>
-#include <memory>
-#include <string>
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-// describes an open _7Z file
-class _7z_file
-{
-public:
-
- // Error types
- enum class error
- {
- NONE = 0,
- OUT_OF_MEMORY,
- FILE_ERROR,
- BAD_SIGNATURE,
- DECOMPRESS_ERROR,
- FILE_TRUNCATED,
- FILE_CORRUPT,
- UNSUPPORTED,
- BUFFER_TOO_SMALL
- };
-
- typedef std::unique_ptr<_7z_file> ptr;
-
-
- virtual ~_7z_file();
-
- /* ----- 7Z file access ----- */
-
- // open a 7Z file and parse its central directory
- static error open(const std::string &filename, ptr &result);
-
- // clear out all open 7Z files from the cache
- static void cache_clear();
-
-
- /* ----- contained file access ----- */
-
- // iterating over files
- virtual int first_file() = 0;
- virtual int next_file() = 0;
-
- // find a file index by crc, filename or both
- 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;
-
- // information on most recently found file
- virtual const std::string &current_name() const = 0;
- virtual std::uint64_t current_uncompressed_length() const = 0;
- virtual std::uint32_t current_crc() const = 0;
-
- // decompress the most recently found file in the _7Z
- virtual error decompress(void *buffer, std::uint32_t length) = 0;
-
-};
-
-#endif // MAME_LIB_UTIL_UN7Z_H
diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp
index 321f4e0b69f..06ab41aae3a 100644
--- a/src/lib/util/unzip.cpp
+++ b/src/lib/util/unzip.cpp
@@ -8,21 +8,25 @@
***************************************************************************/
-#include "osdcore.h"
#include "unzip.h"
+#include "corestr.h"
+#include "osdcore.h"
+
+
#include <algorithm>
#include <array>
#include <cassert>
#include <cstring>
#include <cstdlib>
+#include <mutex>
#include <utility>
#include <vector>
#include <zlib.h>
-
+namespace util {
namespace {
/***************************************************************************
CONSTANTS
@@ -71,29 +75,8 @@ namespace {
#define ZIPCRC 0x0e
#define ZIPSIZE 0x12
#define ZIPUNCMP 0x16
-
-/**
- * @def ZIPFNLN
- *
- * @brief A macro that defines zipfnln.
- */
-
#define ZIPFNLN 0x1a
-
-/**
- * @def ZIPXTRALN
- *
- * @brief A macro that defines zipxtraln.
- */
-
#define ZIPXTRALN 0x1c
-
-/**
- * @def ZIPNAME
- *
- * @brief A macro that defines zipname.
- */
-
#define ZIPNAME 0x1e
@@ -115,6 +98,8 @@ public:
, m_cd()
, m_cd_pos(0)
, m_header()
+ , m_curr_is_dir(false)
+ , m_curr_name()
, m_buffer()
{
std::memset(&m_header, 0, sizeof(m_header));
@@ -123,6 +108,7 @@ public:
static ptr find_cached(const std::string &filename)
{
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++)
{
// if we have a valid entry and it matches our filename, use it and remove from the cache
@@ -139,37 +125,65 @@ public:
static void cache_clear()
{
// clear call cache entries
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { }
}
- zip_file::error initialize()
+ archive_file::error initialize()
{
// read ecd data
auto const ziperr = read_ecd();
- if (ziperr != zip_file::error::NONE)
+ if (ziperr != archive_file::error::NONE)
return ziperr;
// verify that we can work with this zipfile (no disk spanning allowed)
if ((m_ecd.disk_number != m_ecd.cd_start_disk_number) || (m_ecd.cd_disk_entries != m_ecd.cd_total_entries))
- return zip_file::error::UNSUPPORTED;
+ return archive_file::error::UNSUPPORTED;
// allocate memory for the central directory
try { m_cd.resize(m_ecd.cd_size + 1); }
- catch (...) { return zip_file::error::OUT_OF_MEMORY; }
+ catch (...) { return archive_file::error::OUT_OF_MEMORY; }
// read the central directory
std::uint32_t read_length;
auto const filerr = m_file->read(&m_cd[0], m_ecd.cd_start_disk_offset, m_ecd.cd_size, read_length);
if ((filerr != osd_file::error::NONE) || (read_length != m_ecd.cd_size))
- return (filerr == osd_file::error::NONE) ? zip_file::error::FILE_TRUNCATED : zip_file::error::FILE_ERROR;
+ return (filerr == osd_file::error::NONE) ? archive_file::error::FILE_TRUNCATED : archive_file::error::FILE_ERROR;
- return zip_file::error::NONE;
+ return archive_file::error::NONE;
}
- // contained file access
- const zip_file::file_header *first_file();
- const zip_file::file_header *next_file();
- zip_file::error decompress(void *buffer, std::uint32_t length);
+ int first_file()
+ {
+ m_cd_pos = 0;
+ return search(0, std::string(), false, false);
+ }
+ int next_file()
+ {
+ return search(0, std::string(), false, false);
+ }
+ int search(std::uint32_t crc)
+ {
+ m_cd_pos = 0;
+ return search(crc, std::string(), true, false);
+ }
+ int search(const std::string &filename)
+ {
+ m_cd_pos = 0;
+ return search(0, filename, false, true);
+ }
+ int search(std::uint32_t crc, const std::string &filename)
+ {
+ m_cd_pos = 0;
+ return search(crc, filename, true, true);
+ }
+
+ bool current_is_directory() const { return m_curr_is_dir; }
+ const std::string &current_name() const { return m_curr_name; }
+ std::uint64_t current_uncompressed_length() const { return m_header.uncompressed_length; }
+ std::uint32_t current_crc() const { return m_header.crc; }
+
+ archive_file::error decompress(void *buffer, std::uint32_t length);
private:
zip_file_impl(const zip_file_impl &) = delete;
@@ -177,30 +191,47 @@ private:
zip_file_impl &operator=(const zip_file_impl &) = delete;
zip_file_impl &operator=(zip_file_impl &&) = delete;
- zip_file::error reopen()
+ int search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname);
+
+ archive_file::error reopen()
{
if (!m_file)
{
auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, m_file, m_length);
if (filerr != osd_file::error::NONE)
- return zip_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
}
- return zip_file::error::NONE;
+ return archive_file::error::NONE;
}
// ZIP file parsing
- zip_file::error read_ecd();
- zip_file::error get_compressed_data_offset(std::uint64_t &offset);
+ archive_file::error read_ecd();
+ archive_file::error get_compressed_data_offset(std::uint64_t &offset);
// decompression interfaces
- zip_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length);
- zip_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length);
+ archive_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length);
+ archive_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length);
- struct file_header_int : zip_file::file_header
+ struct file_header
{
- std::uint8_t * raw; // pointer to the raw data
- std::uint32_t rawlength; // length of the raw data
- std::uint8_t saved; // saved byte from after filename
+ std::uint32_t signature; // central file header signature
+ std::uint16_t version_created; // version made by
+ std::uint16_t version_needed; // version needed to extract
+ std::uint16_t bit_flag; // general purpose bit flag
+ std::uint16_t compression; // compression method
+ std::uint16_t file_time; // last mod file time
+ std::uint16_t file_date; // last mod file date
+ std::uint32_t crc; // crc-32
+ std::uint32_t compressed_length; // compressed size
+ std::uint32_t uncompressed_length; // uncompressed size
+ std::uint16_t filename_length; // filename length
+ std::uint16_t extra_field_length; // extra field length
+ std::uint16_t file_comment_length; // file comment length
+ std::uint16_t start_disk_number; // disk number start
+ std::uint16_t internal_attributes; // internal file attributes
+ std::uint32_t external_attributes; // external file attributes
+ std::uint32_t local_header_offset; // relative offset of local header
+ const char * filename; // filename
};
// contains extracted end of central directory information
@@ -220,9 +251,10 @@ private:
std::uint32_t rawlength; // length of the raw data
};
- static constexpr std::size_t DECOMPRESS_BUFSIZE = 16384;
- static constexpr std::size_t CACHE_SIZE = 8; // number of open files to cache
- static std::array<ptr, CACHE_SIZE> s_cache;
+ static constexpr std::size_t DECOMPRESS_BUFSIZE = 16384;
+ static constexpr std::size_t CACHE_SIZE = 8; // number of open files to cache
+ static std::array<ptr, CACHE_SIZE> s_cache;
+ static std::mutex s_cache_mutex;
const std::string m_filename; // copy of ZIP filename (for caching)
osd_file::ptr m_file; // OSD file handle
@@ -232,20 +264,32 @@ private:
std::vector<std::uint8_t> m_cd; // central directory raw data
std::uint32_t m_cd_pos; // position in central directory
- file_header_int m_header; // current file header
+ file_header m_header; // current file header
+ bool m_curr_is_dir; // current file is directory
+ std::string m_curr_name; // current file name
std::array<std::uint8_t, DECOMPRESS_BUFSIZE> m_buffer; // buffer for decompression
};
-class zip_file_wrapper : public zip_file
+class zip_file_wrapper : public archive_file
{
public:
zip_file_wrapper(zip_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); }
virtual ~zip_file_wrapper() { zip_file_impl::close(std::move(m_impl)); }
- virtual const file_header *first_file() override { return m_impl->first_file(); }
- virtual const file_header *next_file() override { return m_impl->next_file(); }
+ 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 bool current_is_directory() const override { return m_impl->current_is_directory(); }
+ virtual const std::string &current_name() const override { return m_impl->current_name(); }
+ virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); }
+ virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); }
+
virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
private:
@@ -268,7 +312,7 @@ private:
* @return The word.
*/
-inline UINT16 read_word(UINT8 *buf)
+inline std::uint16_t read_word(std::uint8_t const *buf)
{
return (buf[1] << 8) | buf[0];
}
@@ -283,7 +327,7 @@ inline UINT16 read_word(UINT8 *buf)
* @return The double word.
*/
-inline UINT32 read_dword(UINT8 *buf)
+inline std::uint32_t read_dword(std::uint8_t const *buf)
{
return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
}
@@ -296,6 +340,7 @@ inline UINT32 read_dword(UINT8 *buf)
/** @brief The zip cache[ zip cache size]. */
std::array<zip_file_impl::ptr, zip_file_impl::CACHE_SIZE> zip_file_impl::s_cache;
+std::mutex zip_file_impl::s_cache_mutex;
@@ -320,6 +365,7 @@ void zip_file_impl::close(ptr &&zip)
zip->m_file.reset();
// find the first NULL entry in the cache
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
std::size_t cachenum;
for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
if (!s_cache[cachenum])
@@ -345,88 +391,63 @@ void zip_file_impl::close(ptr &&zip)
in the ZIP
-------------------------------------------------*/
-/**
- * @fn const zip_file_header *zip_file_first_file(zip_file *zip)
- *
- * @brief Zip file first file.
- *
- * @param [in,out] zip If non-null, the zip.
- *
- * @return null if it fails, else a zip_file_header*.
- */
-
-const zip_file::file_header *zip_file_impl::first_file()
-{
- /* reset the position and go from there */
- m_cd_pos = 0;
- return next_file();
-}
-
-
/*-------------------------------------------------
zip_file_next_entry - return the next entry
in the ZIP
-------------------------------------------------*/
-/**
- * @fn const zip_file_header *zip_file_next_file(zip_file *zip)
- *
- * @brief Zip file next file.
- *
- * @param [in,out] zip If non-null, the zip.
- *
- * @return null if it fails, else a zip_file_header*.
- */
-
-const zip_file::file_header *zip_file_impl::next_file()
+int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname)
{
- // fix up any modified data
- if (m_header.raw)
+ // if we're at or past the end, we're done
+ std::string filename;
+ while (m_cd_pos <= m_ecd.cd_size)
{
- m_header.raw[ZIPCFN + m_header.filename_length] = m_header.saved;
- m_header.raw = nullptr;
- }
+ // extract file header info
+ std::uint8_t const *const raw = &m_cd[0] + m_cd_pos;
+ m_header.signature = read_dword(raw + ZIPCENSIG);
+ m_header.version_created = read_word (raw + ZIPCVER);
+ m_header.version_needed = read_word (raw + ZIPCVXT);
+ m_header.bit_flag = read_word (raw + ZIPCFLG);
+ m_header.compression = read_word (raw + ZIPCMTHD);
+ m_header.file_time = read_word (raw + ZIPCTIM);
+ m_header.file_date = read_word (raw + ZIPCDAT);
+ m_header.crc = read_dword(raw + ZIPCCRC);
+ m_header.compressed_length = read_dword(raw + ZIPCSIZ);
+ m_header.uncompressed_length = read_dword(raw + ZIPCUNC);
+ m_header.filename_length = read_word (raw + ZIPCFNL);
+ m_header.extra_field_length = read_word (raw + ZIPCXTL);
+ m_header.file_comment_length = read_word (raw + ZIPCCML);
+ m_header.start_disk_number = read_word (raw + ZIPDSK);
+ m_header.internal_attributes = read_word (raw + ZIPINT);
+ m_header.external_attributes = read_dword(raw + ZIPEXT);
+ m_header.local_header_offset = read_dword(raw + ZIPOFST);
+ m_header.filename = reinterpret_cast<const char *>(raw + ZIPCFN);
+
+ // make sure we have enough data
+ std::uint32_t const rawlength = ZIPCFN + m_header.filename_length + m_header.extra_field_length + m_header.file_comment_length;
+ if ((m_cd_pos + rawlength) > m_ecd.cd_size)
+ break;
- // if we're at or past the end, we're done
- if (m_cd_pos >= m_ecd.cd_size)
- return nullptr;
-
- // extract file header info
- m_header.raw = &m_cd[0] + m_cd_pos;
- m_header.rawlength = ZIPCFN;
- m_header.signature = read_dword(m_header.raw + ZIPCENSIG);
- m_header.version_created = read_word (m_header.raw + ZIPCVER);
- m_header.version_needed = read_word (m_header.raw + ZIPCVXT);
- m_header.bit_flag = read_word (m_header.raw + ZIPCFLG);
- m_header.compression = read_word (m_header.raw + ZIPCMTHD);
- m_header.file_time = read_word (m_header.raw + ZIPCTIM);
- m_header.file_date = read_word (m_header.raw + ZIPCDAT);
- m_header.crc = read_dword(m_header.raw + ZIPCCRC);
- m_header.compressed_length = read_dword(m_header.raw + ZIPCSIZ);
- m_header.uncompressed_length = read_dword(m_header.raw + ZIPCUNC);
- m_header.filename_length = read_word (m_header.raw + ZIPCFNL);
- m_header.extra_field_length = read_word (m_header.raw + ZIPCXTL);
- m_header.file_comment_length = read_word (m_header.raw + ZIPCCML);
- m_header.start_disk_number = read_word (m_header.raw + ZIPDSK);
- m_header.internal_attributes = read_word (m_header.raw + ZIPINT);
- m_header.external_attributes = read_dword(m_header.raw + ZIPEXT);
- m_header.local_header_offset = read_dword(m_header.raw + ZIPOFST);
- m_header.filename = reinterpret_cast<const char *>(m_header.raw + ZIPCFN);
-
- // make sure we have enough data
- m_header.rawlength += m_header.filename_length;
- m_header.rawlength += m_header.extra_field_length;
- m_header.rawlength += m_header.file_comment_length;
- if (m_cd_pos + m_header.rawlength > m_ecd.cd_size)
- return nullptr;
-
- // NULL terminate the filename
- m_header.saved = m_header.raw[ZIPCFN + m_header.filename_length];
- m_header.raw[ZIPCFN + m_header.filename_length] = 0;
-
- // advance the position
- m_cd_pos += m_header.rawlength;
- return &m_header;
+ // advance the position
+ m_cd_pos += rawlength;
+
+ // copy the filename filename
+ bool const is_dir((m_header.filename_length > 0) && (m_header.filename[m_header.filename_length - 1] == '/'));
+ filename.assign(m_header.filename, m_header.filename_length - (is_dir ? 1 : 0));
+
+ // 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()));
+
+ bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch);
+ if (found)
+ {
+ m_curr_is_dir = is_dir;
+ m_curr_name = std::move(filename);
+ return 0;
+ }
+ }
+ return -1;
}
@@ -447,22 +468,22 @@ const zip_file::file_header *zip_file_impl::next_file()
* @return A zip_error.
*/
-zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length)
+archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length)
{
- zip_file::error ziperr;
+ archive_file::error ziperr;
std::uint64_t offset;
// if we don't have enough buffer, error
if (length < m_header.uncompressed_length)
- return zip_file::error::BUFFER_TOO_SMALL;
+ return archive_file::error::BUFFER_TOO_SMALL;
// make sure the info in the header aligns with what we know
if (m_header.start_disk_number != m_ecd.disk_number)
- return zip_file::error::UNSUPPORTED;
+ return archive_file::error::UNSUPPORTED;
// get the compressed data offset
ziperr = get_compressed_data_offset(offset);
- if (ziperr != zip_file::error::NONE)
+ if (ziperr != archive_file::error::NONE)
return ziperr;
// handle compression types
@@ -477,7 +498,7 @@ zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length)
break;
default:
- ziperr = zip_file::error::UNSUPPORTED;
+ ziperr = archive_file::error::UNSUPPORTED;
break;
}
return ziperr;
@@ -503,11 +524,11 @@ zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length)
* @return The ecd.
*/
-zip_file::error zip_file_impl::read_ecd()
+archive_file::error zip_file_impl::read_ecd()
{
// make sure the file handle is open
auto const ziperr = reopen();
- if (ziperr != zip_file::error::NONE)
+ if (ziperr != archive_file::error::NONE)
return ziperr;
// we may need multiple tries
@@ -521,13 +542,13 @@ zip_file::error zip_file_impl::read_ecd()
// allocate buffer
std::unique_ptr<std::uint8_t []> buffer;
try { buffer.reset(new std::uint8_t[buflen + 1]); }
- catch (...) { return zip_file::error::OUT_OF_MEMORY; }
+ catch (...) { return archive_file::error::OUT_OF_MEMORY; }
// read in one buffers' worth of data
std::uint32_t read_length;
auto const error = m_file->read(&buffer[0], m_length - buflen, buflen, read_length);
if (error != osd_file::error::NONE || read_length != buflen)
- return zip_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
// find the ECD signature
std::int32_t offset;
@@ -556,16 +577,16 @@ zip_file::error zip_file_impl::read_ecd()
m_ecd.cd_start_disk_offset = read_dword(&m_ecd.raw[ZIPEOFST]);
m_ecd.comment_length = read_word (&m_ecd.raw[ZIPECOML]);
m_ecd.comment = reinterpret_cast<const char *>(&m_ecd.raw[ZIPECOM]);
- return zip_file::error::NONE;
+ return archive_file::error::NONE;
}
// didn't find it; free this buffer and expand our search
if (buflen < m_length)
buflen *= 2;
else
- return zip_file::error::BAD_SIGNATURE;
+ return archive_file::error::BAD_SIGNATURE;
}
- return zip_file::error::OUT_OF_MEMORY;
+ return archive_file::error::OUT_OF_MEMORY;
}
@@ -585,25 +606,25 @@ zip_file::error zip_file_impl::read_ecd()
* @return The compressed data offset.
*/
-zip_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset)
+archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset)
{
// make sure the file handle is open
auto const ziperr = reopen();
- if (ziperr != zip_file::error::NONE)
+ if (ziperr != archive_file::error::NONE)
return ziperr;
// now go read the fixed-sized part of the local file header
std::uint32_t read_length;
auto const error = m_file->read(&m_buffer[0], m_header.local_header_offset, ZIPNAME, read_length);
if (error != osd_file::error::NONE || read_length != ZIPNAME)
- return (error == osd_file::error::NONE) ? zip_file::error::FILE_TRUNCATED : zip_file::error::FILE_ERROR;
+ return (error == osd_file::error::NONE) ? archive_file::error::FILE_TRUNCATED : archive_file::error::FILE_ERROR;
/* compute the final offset */
offset = m_header.local_header_offset + ZIPNAME;
offset += read_word(&m_buffer[ZIPFNLN]);
offset += read_word(&m_buffer[ZIPXTRALN]);
- return zip_file::error::NONE;
+ return archive_file::error::NONE;
}
@@ -630,18 +651,18 @@ zip_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset)
* @return A zip_error.
*/
-zip_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length)
+archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length)
{
std::uint32_t read_length;
// the data is uncompressed; just read it
auto const filerr = m_file->read(buffer, offset, m_header.compressed_length, read_length);
if (filerr != osd_file::error::NONE)
- return zip_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
else if (read_length != m_header.compressed_length)
- return zip_file::error::FILE_TRUNCATED;
+ return archive_file::error::FILE_TRUNCATED;
else
- return zip_file::error::NONE;
+ return archive_file::error::NONE;
}
@@ -663,14 +684,14 @@ zip_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void
* @return A zip_error.
*/
-zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length)
+archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length)
{
std::uint32_t input_remaining = m_header.compressed_length;
int zerr;
// make sure we don't need a newer mechanism
if (m_header.version_needed > 0x14)
- return zip_file::error::UNSUPPORTED;
+ return archive_file::error::UNSUPPORTED;
/* reset the stream */
z_stream stream;
@@ -681,7 +702,7 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void
// initialize the decompressor
zerr = inflateInit2(&stream, -MAX_WBITS);
if (zerr != Z_OK)
- return zip_file::error::DECOMPRESS_ERROR;
+ return archive_file::error::DECOMPRESS_ERROR;
// loop until we're done
while (1)
@@ -692,7 +713,7 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void
if (filerr != osd_file::error::NONE)
{
inflateEnd(&stream);
- return zip_file::error::FILE_ERROR;
+ return archive_file::error::FILE_ERROR;
}
offset += read_length;
@@ -700,7 +721,7 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void
if (read_length == 0 && input_remaining > 0)
{
inflateEnd(&stream);
- return zip_file::error::FILE_TRUNCATED;
+ return archive_file::error::FILE_TRUNCATED;
}
// fill out the input data
@@ -719,20 +740,20 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void
if (zerr != Z_OK)
{
inflateEnd(&stream);
- return zip_file::error::DECOMPRESS_ERROR;
+ return archive_file::error::DECOMPRESS_ERROR;
}
}
// finish decompression
zerr = inflateEnd(&stream);
if (zerr != Z_OK)
- return zip_file::error::DECOMPRESS_ERROR;
+ return archive_file::error::DECOMPRESS_ERROR;
/* if anything looks funny, report an error */
if (stream.avail_out > 0 || input_remaining > 0)
- return zip_file::error::DECOMPRESS_ERROR;
+ return archive_file::error::DECOMPRESS_ERROR;
- return zip_file::error::NONE;
+ return archive_file::error::NONE;
}
} // anonymous namespace
@@ -740,6 +761,14 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void
/***************************************************************************
+ un7z.cpp TRAMPOLINES
+***************************************************************************/
+
+void m7z_file_cache_clear();
+
+
+
+/***************************************************************************
ZIP FILE ACCESS
***************************************************************************/
@@ -758,10 +787,10 @@ zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void
* @return A zip_error.
*/
-zip_file::error zip_file::open(const std::string &filename, ptr &zip)
+archive_file::error archive_file::open_zip(const std::string &filename, ptr &result)
{
// ensure we start with a NULL result
- zip.reset();
+ result.reset();
// see if we are in the cache, and reopen if so
zip_file_impl::ptr newimpl(zip_file_impl::find_cached(filename));
@@ -777,7 +806,7 @@ zip_file::error zip_file::open(const std::string &filename, ptr &zip)
try
{
- zip = std::make_unique<zip_file_wrapper>(std::move(newimpl));
+ result = std::make_unique<zip_file_wrapper>(std::move(newimpl));
return error::NONE;
}
catch (...)
@@ -793,18 +822,15 @@ zip_file::error zip_file::open(const std::string &filename, ptr &zip)
cache and free all memory
-------------------------------------------------*/
-/**
- * @fn void zip_file_cache_clear(void)
- *
- * @brief Zip file cache clear.
- */
-
-void zip_file::cache_clear()
+void archive_file::cache_clear()
{
zip_file_impl::cache_clear();
+ m7z_file_cache_clear();
}
-zip_file::~zip_file()
+archive_file::~archive_file()
{
}
+
+} // namespace util
diff --git a/src/lib/util/unzip.h b/src/lib/util/unzip.h
index 2882cda0fc3..5fafaec57a4 100644
--- a/src/lib/util/unzip.h
+++ b/src/lib/util/unzip.h
@@ -4,7 +4,7 @@
unzip.h
- ZIP file management.
+ archive file management.
***************************************************************************/
@@ -20,12 +20,14 @@
#include <string>
+namespace util {
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-// describes an open ZIP file
-class zip_file
+// describes an open archive file
+class archive_file
{
public:
@@ -43,55 +45,45 @@ public:
BUFFER_TOO_SMALL
};
- // contains extracted file header information
- struct file_header
- {
- std::uint32_t signature; // central file header signature
- std::uint16_t version_created; // version made by
- std::uint16_t version_needed; // version needed to extract
- std::uint16_t bit_flag; // general purpose bit flag
- std::uint16_t compression; // compression method
- std::uint16_t file_time; // last mod file time
- std::uint16_t file_date; // last mod file date
- std::uint32_t crc; // crc-32
- std::uint32_t compressed_length; // compressed size
- std::uint32_t uncompressed_length; // uncompressed size
- std::uint16_t filename_length; // filename length
- std::uint16_t extra_field_length; // extra field length
- std::uint16_t file_comment_length; // file comment length
- std::uint16_t start_disk_number; // disk number start
- std::uint16_t internal_attributes; // internal file attributes
- std::uint32_t external_attributes; // external file attributes
- std::uint32_t local_header_offset; // relative offset of local header
- const char * filename; // filename
- };
-
- typedef std::unique_ptr<zip_file> ptr;
+ typedef std::unique_ptr<archive_file> ptr;
- /* ----- ZIP file access ----- */
+ /* ----- archive file access ----- */
// open a ZIP file and parse its central directory
- static error open(const std::string &filename, ptr &zip);
+ static error open_zip(const std::string &filename, ptr &zip);
+
+ // open a 7Z file and parse its central directory
+ static error open_7z(const std::string &filename, ptr &result);
- // close a ZIP file (may actually be left open due to caching)
- virtual ~zip_file();
+ // close an archive file (may actually be left open due to caching)
+ virtual ~archive_file();
- // clear out all open ZIP files from the cache
+ // clear out all open files from the cache
static void cache_clear();
/* ----- contained file access ----- */
- // find the first file in the ZIP
- virtual const file_header *first_file() = 0;
+ // iterating over files - returns negative on reaching end
+ virtual int first_file() = 0;
+ virtual int next_file() = 0;
+
+ // 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;
- // find the next file in the ZIP
- virtual const file_header *next_file() = 0;
+ // information on most recently found file
+ virtual bool current_is_directory() const = 0;
+ virtual const std::string &current_name() const = 0;
+ virtual std::uint64_t current_uncompressed_length() const = 0;
+ virtual std::uint32_t current_crc() const = 0;
// decompress the most recently found file in the ZIP
virtual error decompress(void *buffer, std::uint32_t length) = 0;
};
+} // namespace util
#endif // MAME_LIB_UTIL_UNZIP_H
diff --git a/src/lib/util/vecstream.h b/src/lib/util/vecstream.h
index bf144501253..fda218c3e68 100644
--- a/src/lib/util/vecstream.h
+++ b/src/lib/util/vecstream.h
@@ -320,11 +320,10 @@ public:
basic_ivectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { }
basic_ivectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { }
- basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_istream<CharT, Traits>::rdbuf()); }
+ basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return static_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_istream<CharT, Traits>::rdbuf()); }
vector_type const &vec() const { return rdbuf()->vec(); }
void vec(const vector_type &content) { rdbuf()->vec(content); }
void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); }
- basic_ivectorstream &clear() { rdbuf()->clear(); return *this; }
void swap(basic_ivectorstream &that) { std::basic_istream<CharT, Traits>::swap(that); rdbuf()->swap(*that.rdbuf()); }
@@ -342,12 +341,11 @@ public:
basic_ovectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { }
basic_ovectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { }
- basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_ostream<CharT, Traits>::rdbuf()); }
+ basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return static_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_ostream<CharT, Traits>::rdbuf()); }
vector_type const &vec() const { return rdbuf()->vec(); }
void vec(const vector_type &content) { rdbuf()->vec(content); }
void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); }
- basic_ovectorstream &clear() { rdbuf()->clear(); return *this; }
basic_ovectorstream &reserve(typename vector_type::size_type size) { rdbuf()->reserve(size); return *this; }
void swap(basic_ovectorstream &that) { std::basic_ostream<CharT, Traits>::swap(that); rdbuf()->swap(*that.rdbuf()); }
@@ -366,12 +364,11 @@ public:
basic_vectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { }
basic_vectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { }
- basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_iostream<CharT, Traits>::rdbuf()); }
+ basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return static_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_iostream<CharT, Traits>::rdbuf()); }
vector_type const &vec() const { return rdbuf()->vec(); }
void vec(const vector_type &content) { rdbuf()->vec(content); }
void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); }
- basic_vectorstream &clear() { rdbuf()->clear(); return *this; }
basic_vectorstream &reserve(typename vector_type::size_type size) { rdbuf()->reserve(size); return *this; }
void swap(basic_vectorstream &that) { std::basic_iostream<CharT, Traits>::swap(that); rdbuf()->swap(*that.rdbuf()); }
diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp
index 18e2031dcdd..a8fddb64b85 100644
--- a/src/lib/util/zippath.cpp
+++ b/src/lib/util/zippath.cpp
@@ -18,6 +18,8 @@
#include "osdcore.h"
+namespace util {
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
@@ -66,7 +68,7 @@ public:
/** @brief true to called zip first. */
bool called_zip_first;
/** @brief The zipfile. */
- zip_file::ptr zipfile;
+ archive_file::ptr zipfile;
/** @brief The zipprefix. */
std::string zipprefix;
/** @brief The returned dirlist. */
@@ -78,7 +80,7 @@ public:
FUNCTION PROTOTYPES
***************************************************************************/
-static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, const char *subpath, osd_dir_entry_type *type);
+static int zippath_find_sub_path(archive_file &zipfile, const char *subpath, osd_dir_entry_type *type);
static int is_zip_file(const char *path);
static int is_zip_file_separator(char c);
static int is_7z_file(const char *path);
@@ -255,7 +257,7 @@ std::string &zippath_combine(std::string &dst, const char *path1, const char *pa
-------------------------------------------------*/
/**
- * @fn static osd_file::error file_error_from_zip_error(zip_file::error ziperr)
+ * @fn static osd_file::error file_error_from_zip_error(archive_file::error ziperr)
*
* @brief File error from zip error.
*
@@ -264,26 +266,26 @@ std::string &zippath_combine(std::string &dst, const char *path1, const char *pa
* @return A osd_file::error.
*/
-static osd_file::error file_error_from_zip_error(zip_file::error ziperr)
+static osd_file::error file_error_from_zip_error(archive_file::error ziperr)
{
osd_file::error filerr;
switch(ziperr)
{
- case zip_file::error::NONE:
+ case archive_file::error::NONE:
filerr = osd_file::error::NONE;
break;
- case zip_file::error::OUT_OF_MEMORY:
+ case archive_file::error::OUT_OF_MEMORY:
filerr = osd_file::error::OUT_OF_MEMORY;
break;
- case zip_file::error::BAD_SIGNATURE:
- case zip_file::error::DECOMPRESS_ERROR:
- case zip_file::error::FILE_TRUNCATED:
- case zip_file::error::FILE_CORRUPT:
- case zip_file::error::UNSUPPORTED:
- case zip_file::error::FILE_ERROR:
+ case archive_file::error::BAD_SIGNATURE:
+ case archive_file::error::DECOMPRESS_ERROR:
+ case archive_file::error::FILE_TRUNCATED:
+ case archive_file::error::FILE_CORRUPT:
+ case archive_file::error::UNSUPPORTED:
+ case archive_file::error::FILE_ERROR:
filerr = osd_file::error::INVALID_DATA;
break;
- case zip_file::error::BUFFER_TOO_SMALL:
+ case archive_file::error::BUFFER_TOO_SMALL:
default:
filerr = osd_file::error::FAILURE;
break;
@@ -298,7 +300,7 @@ static osd_file::error file_error_from_zip_error(zip_file::error ziperr)
-------------------------------------------------*/
/**
- * @fn static osd_file::error create_core_file_from_zip(zip_file *zip, const zip_file_header *header, util::core_file::ptr &file)
+ * @fn static osd_file::error create_core_file_from_zip(archive_file *zip, util::core_file::ptr &file)
*
* @brief Creates core file from zip.
*
@@ -309,27 +311,27 @@ static osd_file::error file_error_from_zip_error(zip_file::error ziperr)
* @return The new core file from zip.
*/
-static osd_file::error create_core_file_from_zip(zip_file &zip, const zip_file::file_header *header, util::core_file::ptr &file)
+static osd_file::error create_core_file_from_zip(archive_file &zip, util::core_file::ptr &file)
{
osd_file::error filerr;
- zip_file::error ziperr;
+ archive_file::error ziperr;
void *ptr;
- ptr = malloc(header->uncompressed_length);
+ ptr = malloc(zip.current_uncompressed_length());
if (ptr == nullptr)
{
filerr = osd_file::error::OUT_OF_MEMORY;
goto done;
}
- ziperr = zip.decompress(ptr, header->uncompressed_length);
- if (ziperr != zip_file::error::NONE)
+ ziperr = zip.decompress(ptr, zip.current_uncompressed_length());
+ if (ziperr != archive_file::error::NONE)
{
filerr = file_error_from_zip_error(ziperr);
goto done;
}
- filerr = util::core_file::open_ram_copy(ptr, header->uncompressed_length, OPEN_FLAG_READ, file);
+ filerr = util::core_file::open_ram_copy(ptr, zip.current_uncompressed_length(), OPEN_FLAG_READ, file);
if (filerr != osd_file::error::NONE)
goto done;
@@ -360,9 +362,9 @@ done:
osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path)
{
osd_file::error filerr = osd_file::error::NOT_FOUND;
- zip_file::error ziperr;
- zip_file::ptr zip;
- const zip_file::file_header *header;
+ archive_file::error ziperr;
+ archive_file::ptr zip;
+ int header;
osd_dir_entry_type entry_type;
int len;
@@ -379,8 +381,8 @@ osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core
if (is_zip_file(mainpath.c_str()))
{
/* this file might be a zip file - lets take a look */
- ziperr = zip_file::open(mainpath, zip);
- if (ziperr == zip_file::error::NONE)
+ ziperr = archive_file::open_zip(mainpath, zip);
+ if (ziperr == archive_file::error::NONE)
{
/* it is a zip file - error if we're not opening for reading */
if (openflags != OPEN_FLAG_READ)
@@ -394,20 +396,20 @@ osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core
else
header = zip->first_file();
- if (header == nullptr)
+ if (header < 0)
{
filerr = osd_file::error::NOT_FOUND;
goto done;
}
/* attempt to read the file */
- filerr = create_core_file_from_zip(*zip, header, file);
+ filerr = create_core_file_from_zip(*zip, file);
if (filerr != osd_file::error::NONE)
goto done;
/* update subpath, if appropriate */
if (subpath.length() == 0)
- subpath.assign(header->filename);
+ subpath.assign(zip->current_name());
/* we're done */
goto done;
@@ -656,7 +658,7 @@ static char next_path_char(const char *s, int *pos)
-------------------------------------------------*/
/**
- * @fn static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const char *subpath, osd_dir_entry_type *type)
+ * @fn static const zip_file_header *zippath_find_sub_path(archive_file *zipfile, const char *subpath, osd_dir_entry_type *type)
*
* @brief Zippath find sub path.
*
@@ -667,13 +669,9 @@ static char next_path_char(const char *s, int *pos)
* @return null if it fails, else a zip_file_header*.
*/
-static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, const char *subpath, osd_dir_entry_type *type)
+static int zippath_find_sub_path(archive_file &zipfile, const char *subpath, osd_dir_entry_type *type)
{
- int i, j;
- char c1, c2, last_char;
- const zip_file::file_header *header;
-
- for (header = zipfile.first_file(); header != nullptr; header = zipfile.next_file())
+ for (int header = zipfile.first_file(); header >= 0; header = zipfile.next_file())
{
/* special case */
if (subpath == nullptr)
@@ -683,13 +681,12 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con
return header;
}
- i = 0;
- j = 0;
+ // FIXME: how is this actually supposed to work? I'm pretty sure it's broken right now anyway.
+ int i = 0, j = 0;
+ char c1, c2, last_char;
last_char = '/';
- while(((c1 = next_path_char(header->filename, &i)) == (c2 = next_path_char(subpath, &j))) &&
- ( c1 != '\0' && c2 != '\0' ))
- last_char = c2;
-
+ while(((c1 = next_path_char(zipfile.current_name().c_str(), &i)) == (c2 = next_path_char(subpath, &j))) && (c1 != '\0' && c2 != '\0'))
+ last_char = c2;
if (c2 == '\0')
{
@@ -710,7 +707,7 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con
if (type != nullptr)
*type = ENTTYPE_NONE;
- return nullptr;
+ return -1;
}
@@ -721,7 +718,7 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con
-------------------------------------------------*/
/**
- * @fn static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, std::string &newpath)
+ * @fn static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, archive_file *&zipfile, std::string &newpath)
*
* @brief Zippath resolve.
*
@@ -733,7 +730,7 @@ static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, con
* @return A osd_file::error.
*/
-static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file::ptr &zipfile, std::string &newpath)
+static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath)
{
osd_file::error err;
osd_directory_entry *current_entry = nullptr;
@@ -789,7 +786,7 @@ static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &ent
/* is this file a ZIP file? */
if ((current_entry_type == ENTTYPE_FILE) && is_zip_file(apath_trimmed.c_str())
- && (zip_file::open(apath_trimmed, zipfile) == zip_file::error::NONE))
+ && (archive_file::open_zip(apath_trimmed, zipfile) == archive_file::error::NONE))
{
i = strlen(path + apath.length());
while (i > 0 && is_zip_path_separator(path[apath.length() + i - 1]))
@@ -943,15 +940,15 @@ void zippath_closedir(zippath_directory *directory)
* @return null if it fails, else the relative path.
*/
-static const char *get_relative_path(zippath_directory *directory, const zip_file::file_header *header)
+static const char *get_relative_path(zippath_directory *directory)
{
const char *result = nullptr;
int len = directory->zipprefix.length();
- if ((len <= strlen(header->filename))
- && !strncmp(directory->zipprefix.c_str(), header->filename, len))
+ if ((len <= directory->zipfile->current_name().length())
+ && !strncmp(directory->zipprefix.c_str(), directory->zipfile->current_name().c_str(), len))
{
- result = &header->filename[len];
+ result = &directory->zipfile->current_name().c_str()[len];
while(is_zip_file_separator(*result))
result++;
}
@@ -977,7 +974,7 @@ static const char *get_relative_path(zippath_directory *directory, const zip_fil
const osd_directory_entry *zippath_readdir(zippath_directory *directory)
{
const osd_directory_entry *result = nullptr;
- const zip_file::file_header *header;
+ int header;
const char *relpath;
const char *separator;
const char *s;
@@ -1024,7 +1021,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
directory->called_zip_first = true;
relpath = nullptr;
}
- while((header != nullptr) && ((relpath = get_relative_path(directory, header)) == nullptr));
+ while((header >= 0) && ((relpath = get_relative_path(directory)) == nullptr));
if (relpath != nullptr)
{
@@ -1063,7 +1060,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
memset(&directory->returned_entry, 0, sizeof(directory->returned_entry));
directory->returned_entry.name = relpath;
directory->returned_entry.type = ENTTYPE_FILE;
- directory->returned_entry.size = header->uncompressed_length;
+ directory->returned_entry.size = directory->zipfile->current_uncompressed_length();
result = &directory->returned_entry;
}
}
@@ -1094,3 +1091,5 @@ int zippath_is_zip(zippath_directory *directory)
{
return directory->zipfile != nullptr;
}
+
+} // namespace util
diff --git a/src/lib/util/zippath.h b/src/lib/util/zippath.h
index d54dd68c38d..653617d66cc 100644
--- a/src/lib/util/zippath.h
+++ b/src/lib/util/zippath.h
@@ -10,14 +10,16 @@
#pragma once
-#ifndef __ZIPPATH_H__
-#define __ZIPPATH_H__
+#ifndef MAME_LIB_UTIL_ZIPPATH_H
+#define MAME_LIB_UTIL_ZIPPATH_H
#include "corefile.h"
#include <string>
#include "unzip.h"
+namespace util {
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
@@ -62,6 +64,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory);
/* returns TRUE if this path is a ZIP path or FALSE if not */
int zippath_is_zip(zippath_directory *directory);
+} // namespace util
-#endif /* __ZIPPATH_H__ */
+#endif /* MAME_LIB_UTIL_ZIPPATH_H */