diff options
author | 2021-08-22 09:06:15 +1000 | |
---|---|---|
committer | 2021-08-22 09:06:15 +1000 | |
commit | e8bbea1fc6e94e14768509d322f6c624403ffb36 (patch) | |
tree | 74dd1606a900d83de8aecff17a6737af4113308d /src/emu/diimage.cpp | |
parent | e319bde5fc3696d7f48f62b15b6366c4377fe5d1 (diff) |
formats, osd, util: Started refactoring file I/O stuff. (#8456)
Added more modern generic I/O interfaces with implementation backed by stdio, osd_file and core_file, replacing io_generic. Also replaced core_file's build-in zlib compression with a filter.
unzip.cpp, un7z.cpp: Added option to supply abstract I/O interface rather than filename.
Converted osd_file, core_file, archive_file, chd_file and device_image_interface to use std::error_condition rather than their own error enums.
Allow mounting TI-99 RPK from inside archives.
Diffstat (limited to 'src/emu/diimage.cpp')
-rw-r--r-- | src/emu/diimage.cpp | 207 |
1 files changed, 77 insertions, 130 deletions
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 55a9193f3f1..e38b4939a2b 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -10,14 +10,15 @@ #include "emu.h" -#include "corestr.h" #include "emuopts.h" #include "romload.h" -#include "ui/uimain.h" -#include "zippath.h" #include "softlist.h" #include "softlist_dev.h" -#include "formats/ioprocs.h" + +#include "ui/uimain.h" + +#include "corestr.h" +#include "zippath.h" #include <algorithm> #include <cctype> @@ -270,11 +271,8 @@ void device_image_interface::add_format(std::string &&name, std::string &&descri void device_image_interface::clear_error() { - m_err = IMAGE_ERROR_SUCCESS; - if (!m_err_message.empty()) - { - m_err_message.clear(); - } + m_err.clear(); + m_err_message.clear(); } @@ -284,21 +282,38 @@ void device_image_interface::clear_error() // error //------------------------------------------------- -static std::string_view messages[] = +std::error_category const &image_category() noexcept { - "", - "Internal error", - "Unsupported operation", - "Out of memory", - "File not found", - "Invalid image", - "File already open", - "Unspecified error" -}; + class image_category_impl : public std::error_category + { + public: + virtual char const *name() const noexcept override { return "image"; } + + virtual std::string message(int condition) const override + { + using namespace std::literals; + static std::string_view const s_messages[] = { + "No error"sv, + "Internal error"sv, + "Unsupported operation"sv, + "Invalid image"sv, + "File already open"sv, + "Unspecified error"sv }; + if ((0 <= condition) && (std::size(s_messages) > condition)) + return std::string(s_messages[condition]); + else + return "Unknown error"s; + } + }; + static image_category_impl const s_image_category_instance; + return s_image_category_instance; +} std::string_view device_image_interface::error() { - return (!m_err_message.empty()) ? m_err_message : messages[m_err]; + if (m_err && m_err_message.empty()) + m_err_message = m_err.message(); + return m_err_message; } @@ -307,14 +322,12 @@ std::string_view device_image_interface::error() // seterror - specifies an error on an image //------------------------------------------------- -void device_image_interface::seterror(image_error_t err, const char *message) +void device_image_interface::seterror(std::error_condition err, const char *message) { clear_error(); m_err = err; - if (message != nullptr) - { + if (message) m_err_message = message; - } } @@ -544,14 +557,13 @@ void device_image_interface::battery_load(void *buffer, int length, int fill) if (!buffer || (length <= 0)) throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length"); - osd_file::error filerr; - int bytes_read = 0; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); + std::string const fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); /* try to open the battery file and read it in, if possible */ emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ); - filerr = file.open(fname); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + int bytes_read = 0; + if (!filerr) bytes_read = file.read(buffer, length); // fill remaining bytes (if necessary) @@ -563,14 +575,13 @@ void device_image_interface::battery_load(void *buffer, int length, const void * if (!buffer || (length <= 0)) throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length"); - osd_file::error filerr; - int bytes_read = 0; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); + std::string const fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); // try to open the battery file and read it in, if possible emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ); - filerr = file.open(fname); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + int bytes_read = 0; + if (!filerr) bytes_read = file.read(buffer, length); // if no file was present, copy the default contents @@ -598,8 +609,8 @@ void device_image_interface::battery_save(const void *buffer, int length) // try to open the battery file and write it out, if possible emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = file.open(fname); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + if (!filerr) file.write(buffer, length); } @@ -637,58 +648,30 @@ bool device_image_interface::uses_file_extension(const char *file_extension) con // *************************************************************************** //------------------------------------------------- -// image_error_from_file_error - converts an image -// error to a file error -//------------------------------------------------- - -image_error_t device_image_interface::image_error_from_file_error(osd_file::error filerr) -{ - switch (filerr) - { - case osd_file::error::NONE: - return IMAGE_ERROR_SUCCESS; - - case osd_file::error::NOT_FOUND: - case osd_file::error::ACCESS_DENIED: - // file not found (or otherwise cannot open) - return IMAGE_ERROR_FILENOTFOUND; - - case osd_file::error::OUT_OF_MEMORY: - // out of memory - return IMAGE_ERROR_OUTOFMEMORY; - - case osd_file::error::ALREADY_OPEN: - // this shouldn't happen - return IMAGE_ERROR_ALREADYOPEN; - - case osd_file::error::FAILURE: - case osd_file::error::TOO_MANY_FILES: - case osd_file::error::INVALID_DATA: - default: - // other errors - return IMAGE_ERROR_INTERNAL; - } -} - - -//------------------------------------------------- // load_image_by_path - loads an image with a // specific path //------------------------------------------------- -image_error_t device_image_interface::load_image_by_path(u32 open_flags, std::string_view path) +std::error_condition device_image_interface::load_image_by_path(u32 open_flags, std::string_view path) { std::string revised_path; // attempt to read the file - auto const filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); - if (filerr != osd_file::error::NONE) - return image_error_from_file_error(filerr); + auto filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); + if (filerr) + { + osd_printf_verbose("%s: error opening image file %s with flags=%08X (%s:%d %s)\n", device().tag(), path, open_flags, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; + } + else + { + osd_printf_verbose("%s: opened image file %s with flags=%08X\n", device().tag(), path, open_flags); + } m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1; m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0; set_image_filename(revised_path); - return IMAGE_ERROR_SUCCESS; + return std::error_condition(); } @@ -696,7 +679,7 @@ image_error_t device_image_interface::load_image_by_path(u32 open_flags, std::st // reopen_for_write //------------------------------------------------- -int device_image_interface::reopen_for_write(std::string_view path) +std::error_condition device_image_interface::reopen_for_write(std::string_view path) { m_file.reset(); @@ -704,15 +687,15 @@ int device_image_interface::reopen_for_write(std::string_view path) // attempt to open the file for writing auto const filerr = util::zippath_fopen(path, OPEN_FLAG_READ|OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, m_file, revised_path); - if (filerr != osd_file::error::NONE) - return image_error_from_file_error(filerr); + if (filerr) + return filerr; // success! m_readonly = 0; m_created = 1; set_image_filename(revised_path); - return IMAGE_ERROR_SUCCESS; + return std::error_condition(); } @@ -823,19 +806,19 @@ bool device_image_interface::load_software(software_list_device &swlist, std::st // try to load the file m_mame_file.reset(new emu_file(device().machine().options().media_path(), searchpath, OPEN_FLAG_READ)); m_mame_file->set_restrict_to_mediapath(1); - osd_file::error filerr; + std::error_condition filerr; if (has_crc) filerr = m_mame_file->open(romp->name(), crc); else filerr = m_mame_file->open(romp->name()); - if (filerr != osd_file::error::NONE) + if (filerr) m_mame_file.reset(); warningcount += verify_length_and_hash(m_mame_file.get(), romp->name(), romp->get_length(), util::hash_collection(romp->hashdata())); - if (filerr == osd_file::error::NONE) + if (!filerr) filerr = util::core_file::open_proxy(*m_mame_file, m_file); - if (filerr == osd_file::error::NONE) + if (!filerr) retval = true; break; // load first item for start @@ -878,14 +861,14 @@ image_init_result device_image_interface::load_internal(std::string_view path, b { // open the file m_err = load_image_by_path(*iter, path); - if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) + if (m_err && (m_err != std::errc::no_such_file_or_directory) && (m_err != std::errc::permission_denied)) goto done; } // did we fail to find the file? if (!m_file) { - m_err = IMAGE_ERROR_FILENOTFOUND; + m_err = std::errc::no_such_file_or_directory; goto done; } } @@ -894,15 +877,17 @@ image_init_result device_image_interface::load_internal(std::string_view path, b m_create_format = create_format; m_create_args = create_args; - if (init_phase()==false) { - m_err = (finish_load() == image_init_result::PASS) ? IMAGE_ERROR_SUCCESS : IMAGE_ERROR_INTERNAL; + if (!init_phase()) + { + m_err = (finish_load() == image_init_result::PASS) ? std::error_condition() : image_error::INTERNAL; if (m_err) goto done; } // success! done: - if (m_err!=0) { + if (m_err) + { if (!init_phase()) { if (device().machine().phase() == machine_phase::RUNNING) @@ -1004,7 +989,7 @@ image_init_result device_image_interface::finish_load() { if (!image_checkhash()) { - m_err = IMAGE_ERROR_INVALIDIMAGE; + m_err = image_error::INVALIDIMAGE; err = image_init_result::FAIL; } @@ -1016,7 +1001,7 @@ image_init_result device_image_interface::finish_load() if (err != image_init_result::PASS) { if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; + m_err = image_error::UNSPECIFIED; } } else @@ -1026,7 +1011,7 @@ image_init_result device_image_interface::finish_load() if (err != image_init_result::PASS) { if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; + m_err = image_error::UNSPECIFIED; } } } @@ -1354,41 +1339,3 @@ bool device_image_interface::init_phase() const return !device().has_running_machine() || device().machine().phase() == machine_phase::INIT; } - - -//---------------------------------------------------------------------------- - -static int image_fseek_thunk(void *file, s64 offset, int whence) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fseek(offset, whence); -} - -static size_t image_fread_thunk(void *file, void *buffer, size_t length) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fread(buffer, length); -} - -static size_t image_fwrite_thunk(void *file, const void *buffer, size_t length) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fwrite(buffer, length); -} - -static u64 image_fsize_thunk(void *file) -{ - device_image_interface *image = (device_image_interface *) file; - return image->length(); -} - -//---------------------------------------------------------------------------- - -struct io_procs image_ioprocs = -{ - nullptr, - image_fseek_thunk, - image_fread_thunk, - image_fwrite_thunk, - image_fsize_thunk -}; |