diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua index 7766b69873d..4094e48c6be 100644 --- a/scripts/src/osd/sdl.lua +++ b/scripts/src/osd/sdl.lua @@ -461,7 +461,6 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/strconv.h", MAME_DIR .. "src/osd/osdsync.cpp", MAME_DIR .. "src/osd/osdsync.h", - MAME_DIR .. "src/osd/sdl/sdldir.cpp", MAME_DIR .. "src/osd/modules/osdmodule.cpp", MAME_DIR .. "src/osd/modules/osdmodule.h", MAME_DIR .. "src/osd/modules/lib/osdlib_" .. SDLOS_TARGETOS .. ".cpp", @@ -470,6 +469,7 @@ project ("ocore_" .. _OPTIONS["osd"]) if BASE_TARGETOS=="unix" then files { + MAME_DIR .. "src/osd/modules/file/posixdir.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.h", MAME_DIR .. "src/osd/modules/file/posixptty.cpp", @@ -480,6 +480,7 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/windows", } files { + MAME_DIR .. "src/osd/modules/file/windir.cpp", MAME_DIR .. "src/osd/modules/file/winfile.cpp", MAME_DIR .. "src/osd/modules/file/winfile.h", MAME_DIR .. "src/osd/modules/file/winptty.cpp", diff --git a/scripts/src/osd/windows.lua b/scripts/src/osd/windows.lua index 9307c6dec71..a6e40c7aadc 100644 --- a/scripts/src/osd/windows.lua +++ b/scripts/src/osd/windows.lua @@ -244,13 +244,13 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/osdsync.cpp", MAME_DIR .. "src/osd/osdsync.h", MAME_DIR .. "src/osd/windows/main.cpp", - MAME_DIR .. "src/osd/windows/windir.cpp", MAME_DIR .. "src/osd/windows/winutf8.cpp", MAME_DIR .. "src/osd/windows/winutf8.h", MAME_DIR .. "src/osd/windows/winutil.cpp", MAME_DIR .. "src/osd/windows/winutil.h", MAME_DIR .. "src/osd/modules/osdmodule.cpp", MAME_DIR .. "src/osd/modules/osdmodule.h", + MAME_DIR .. "src/osd/modules/file/windir.cpp", MAME_DIR .. "src/osd/modules/file/winfile.cpp", MAME_DIR .. "src/osd/modules/file/winfile.h", MAME_DIR .. "src/osd/modules/file/winptty.cpp", diff --git a/src/devices/bus/nubus/nubus_image.cpp b/src/devices/bus/nubus/nubus_image.cpp index d7752e3babc..2a13a9c8613 100644 --- a/src/devices/bus/nubus/nubus_image.cpp +++ b/src/devices/bus/nubus/nubus_image.cpp @@ -271,7 +271,7 @@ READ32_MEMBER( nubus_image_device::image_super_r ) WRITE32_MEMBER( nubus_image_device::file_cmd_w ) { - const osd_directory_entry *dp; + const osd::directory::entry *dp; char fullpath[1024]; UINT64 filesize; @@ -290,11 +290,10 @@ WRITE32_MEMBER( nubus_image_device::file_cmd_w ) } break; case kFileCmdGetFirstListing: - if(filectx.dirp) osd_closedir(filectx.dirp); - filectx.dirp = osd_opendir((const char *)filectx.curdir); + filectx.dirp = osd::directory::open((const char *)filectx.curdir); case kFileCmdGetNextListing: if (filectx.dirp) { - dp = osd_readdir(filectx.dirp); + dp = filectx.dirp->read(); if(dp) { strncpy((char*)filectx.filename, dp->name, sizeof(filectx.filename)); } else { diff --git a/src/devices/bus/nubus/nubus_image.h b/src/devices/bus/nubus/nubus_image.h index dda6e55fc02..6badecd4f0d 100644 --- a/src/devices/bus/nubus/nubus_image.h +++ b/src/devices/bus/nubus/nubus_image.h @@ -18,7 +18,7 @@ struct nbfilectx { UINT32 curcmd; UINT8 filename[128]; UINT8 curdir[1024]; - osd_directory *dirp; + osd::directory::ptr dirp; osd_file::ptr fd; UINT64 filelen; UINT32 bytecount; diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 9347570fee6..b6c32826a5a 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -295,24 +295,23 @@ void device_image_interface::message(const char *format, ...) -------------------------------------------------*/ bool device_image_interface::try_change_working_directory(const char *subdir) { - osd_directory *directory; - const osd_directory_entry *entry; - bool success = FALSE; - bool done = FALSE; + const osd::directory::entry *entry; + bool success = false; + bool done = false; - directory = osd_opendir(m_working_directory.c_str()); - if (directory != nullptr) + auto directory = osd::directory::open(m_working_directory.c_str()); + if (directory) { - while(!done && (entry = osd_readdir(directory)) != nullptr) + while (!done && (entry = directory->read()) != nullptr) { if (!core_stricmp(subdir, entry->name)) { - done = TRUE; - success = entry->type == ENTTYPE_DIR; + done = true; + success = entry->type == osd::directory::entry::entry_type::DIR; } } - osd_closedir(directory); + directory.reset(); } /* did we successfully identify the directory? */ diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index 78be6e10faa..1fe26071acb 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -89,9 +89,6 @@ file_enumerator::file_enumerator(const char *searchpath) file_enumerator::~file_enumerator() { - // close anything open - if (m_curdir != nullptr) - osd_closedir(m_curdir); } @@ -100,30 +97,29 @@ file_enumerator::~file_enumerator() // in the search path //------------------------------------------------- -const osd_directory_entry *file_enumerator::next() +const osd::directory::entry *file_enumerator::next() { // loop over potentially empty directories while (1) { // if no open directory, get the next path - while (m_curdir == nullptr) + while (!m_curdir) { // if we fail to get anything more, we're done if (!m_iterator.next(m_pathbuffer)) return nullptr; // open the path - m_curdir = osd_opendir(m_pathbuffer.c_str()); + m_curdir = osd::directory::open(m_pathbuffer.c_str()); } // get the next entry from the current directory - const osd_directory_entry *result = osd_readdir(m_curdir); + const osd::directory::entry *result = m_curdir->read(); if (result != nullptr) return result; // we're done; close this directory - osd_closedir(m_curdir); - m_curdir = nullptr; + m_curdir.reset(); } } diff --git a/src/emu/fileio.h b/src/emu/fileio.h index 5e765f660d8..411e211d17b 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -63,13 +63,13 @@ public: ~file_enumerator(); // iterator - const osd_directory_entry *next(); + const osd::directory::entry *next(); private: // internal state - path_iterator m_iterator; - osd_directory * m_curdir; - std::string m_pathbuffer; + path_iterator m_iterator; + osd::directory::ptr m_curdir; + std::string m_pathbuffer; //int m_buflen; }; diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index 778403ef8a4..ae797fc81d2 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -568,7 +568,7 @@ void running_machine::set_saveload_filename(const char *filename) // take into account the statename option const char *stateopt = options().state_name(); std::string statename = get_statename(stateopt); - m_saveload_pending_file.assign(statename.c_str()).append(PATH_SEPARATOR).append(filename).append(".sta"); + m_saveload_pending_file = string_format("%s%s%s.sta", statename, PATH_SEPARATOR, filename); } } @@ -844,7 +844,7 @@ void running_machine::handle_saveload() break; case STATERR_INVALID_HEADER: - popmessage("Error: Unable to %s state due to an invalid header. Make sure the save state is correct for this game.", opname); + popmessage("Error: Unable to %s state due to an invalid header. Make sure the save state is correct for this machine.", opname); break; case STATERR_READ_ERROR: @@ -857,7 +857,7 @@ void running_machine::handle_saveload() case STATERR_NONE: if (!(m_system.flags & MACHINE_SUPPORTS_SAVE)) - popmessage("State successfully %s.\nWarning: Save states are not officially supported for this game.", opnamed); + popmessage("State successfully %s.\nWarning: Save states are not officially supported for this machine.", opnamed); else popmessage("State successfully %s.", opnamed); break; diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 39033e84d20..3679441957a 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -1810,19 +1810,19 @@ media_identifier::media_identifier(emu_options &options) void media_identifier::identify(const char *filename) { // first try to open as a directory - osd_directory *directory = osd_opendir(filename); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(filename); + if (directory) { // iterate over all files in the directory - for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory)) - if (entry->type == ENTTYPE_FILE) + for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) + if (entry->type == osd::directory::entry::entry_type::FILE) { std::string curfile = std::string(filename).append(PATH_SEPARATOR).append(entry->name); identify(curfile.c_str()); } // close the directory and be done - osd_closedir(directory); + directory.reset(); } // if that failed, and the filename ends with .zip, identify as a ZIP file diff --git a/src/frontend/mame/pluginopts.cpp b/src/frontend/mame/pluginopts.cpp index e56a72dfced..0dd9ca7bcf9 100644 --- a/src/frontend/mame/pluginopts.cpp +++ b/src/frontend/mame/pluginopts.cpp @@ -39,13 +39,13 @@ plugin_options::plugin_options() void plugin_options::parse_json(std::string path) { // first try to open as a directory - osd_directory *directory = osd_opendir(path.c_str()); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(path); + if (directory) { // iterate over all files in the directory - for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory)) + for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) { - if (entry->type == ENTTYPE_FILE) + if (entry->type == osd::directory::entry::entry_type::FILE) { std::string name = entry->name; if (name == "plugin.json") @@ -80,7 +80,7 @@ void plugin_options::parse_json(std::string path) } } - else if (entry->type == ENTTYPE_DIR) + else if (entry->type == osd::directory::entry::entry_type::DIR) { std::string name = entry->name; if (!(name == "." || name == "..")) @@ -89,8 +89,5 @@ void plugin_options::parse_json(std::string path) } } } - - // close the directory and be done - osd_closedir(directory); } } diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp index 95a5ead8a8b..4cb4450b9ce 100644 --- a/src/frontend/mame/ui/custui.cpp +++ b/src/frontend/mame/ui/custui.cpp @@ -36,10 +36,10 @@ menu_custom_ui::menu_custom_ui(mame_ui_manager &mui, render_container *container // load languages file_enumerator path(mui.machine().options().language_path()); auto lang = mui.machine().options().language(); - const osd_directory_entry *dirent; + const osd::directory::entry *dirent; int cnt = 0; while ((dirent = path.next()) != nullptr) - if (dirent->type == ENTTYPE_DIR && strcmp(dirent->name, ".") != 0 && strcmp(dirent->name, "..") != 0) + if (dirent->type == osd::directory::entry::entry_type::DIR && strcmp(dirent->name, ".") != 0 && strcmp(dirent->name, "..") != 0) { auto name = std::string(dirent->name); auto i = strreplace(name, "_", " ("); diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp index 359d6d63420..1a500e14482 100644 --- a/src/frontend/mame/ui/dirmenu.cpp +++ b/src/frontend/mame/ui/dirmenu.cpp @@ -466,7 +466,7 @@ void menu_add_change_folder::populate() // open a path const char *volume_name = nullptr; file_enumerator path(m_current_path.c_str()); - const osd_directory_entry *dirent; + const osd::directory::entry *dirent; int folders_count = 0; // add the drives @@ -476,7 +476,7 @@ void menu_add_change_folder::populate() // add the directories while ((dirent = path.next()) != nullptr) { - if (dirent->type == ENTTYPE_DIR && strcmp(dirent->name, ".") != 0) + if (dirent->type == osd::directory::entry::entry_type::DIR && strcmp(dirent->name, ".") != 0) item_append(dirent->name, "[DIR]", 0, (void *)(FPTR)++folders_count); } diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index 7c1d3ccfed6..1fe8c8e0bf4 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -451,7 +451,7 @@ menu_file_selector::file_selector_entry *menu_file_selector::append_entry( // a menu item for a file selector entry //------------------------------------------------- -menu_file_selector::file_selector_entry *menu_file_selector::append_dirent_entry(const osd_directory_entry *dirent) +menu_file_selector::file_selector_entry *menu_file_selector::append_dirent_entry(const osd::directory::entry *dirent) { std::string buffer; file_selector_entry_type entry_type; @@ -459,11 +459,11 @@ menu_file_selector::file_selector_entry *menu_file_selector::append_dirent_entry switch(dirent->type) { - case ENTTYPE_FILE: + case osd::directory::entry::entry_type::FILE: entry_type = SELECTOR_ENTRY_TYPE_FILE; break; - case ENTTYPE_DIR: + case osd::directory::entry::entry_type::DIR: entry_type = SELECTOR_ENTRY_TYPE_DIRECTORY; break; @@ -536,7 +536,7 @@ void menu_file_selector::populate() { util::zippath_directory *directory = nullptr; osd_file::error err; - const osd_directory_entry *dirent; + const osd::directory::entry *dirent; const file_selector_entry *entry; const file_selector_entry *selected_entry = nullptr; int i; diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h index 66be755f699..571c11e4413 100644 --- a/src/frontend/mame/ui/filesel.h +++ b/src/frontend/mame/ui/filesel.h @@ -107,7 +107,7 @@ private: // methods int compare_entries(const file_selector_entry *e1, const file_selector_entry *e2); file_selector_entry *append_entry(file_selector_entry_type entry_type, const char *entry_basename, const char *entry_fullpath); - file_selector_entry *append_dirent_entry(const osd_directory_entry *dirent); + file_selector_entry *append_dirent_entry(const osd::directory::entry *dirent); void append_entry_menu_item(const file_selector_entry *entry); }; diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp index bc713bbca53..3468fa04b2d 100644 --- a/src/frontend/mame/ui/imgcntrl.cpp +++ b/src/frontend/mame/ui/imgcntrl.cpp @@ -88,31 +88,30 @@ menu_control_device_image::~menu_control_device_image() void menu_control_device_image::test_create(bool &can_create, bool &need_confirm) { std::string path; - osd_directory_entry *entry; - osd_dir_entry_type file_type; + osd::directory::entry::entry_type file_type; /* assemble the full path */ util::zippath_combine(path, current_directory.c_str(), current_file.c_str()); /* does a file or a directory exist at the path */ - entry = osd_stat(path.c_str()); - file_type = (entry != nullptr) ? entry->type : ENTTYPE_NONE; + auto entry = osd_stat(path.c_str()); + file_type = (entry != nullptr) ? entry->type : osd::directory::entry::entry_type::NONE; switch(file_type) { - case ENTTYPE_NONE: + case osd::directory::entry::entry_type::NONE: /* no file/dir here - always create */ can_create = true; need_confirm = false; break; - case ENTTYPE_FILE: + case osd::directory::entry::entry_type::FILE: /* a file exists here - ask for permission from the user */ can_create = true; need_confirm = true; break; - case ENTTYPE_DIR: + case osd::directory::entry::entry_type::DIR: /* a directory exists here - we can't save over it */ ui().popup_time(5, "%s", _("Cannot save over directory")); can_create = false; @@ -124,9 +123,6 @@ void menu_control_device_image::test_create(bool &can_create, bool &need_confirm need_confirm = false; fatalerror("Unexpected\n"); } - - if (entry != nullptr) - osd_free(entry); } diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index d9f5cbeef8a..d8693356f05 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -39,7 +39,7 @@ inifile_manager::inifile_manager(running_machine &machine, ui_options &moptions) void inifile_manager::directory_scan() { file_enumerator path(m_options.extraini_path()); - const osd_directory_entry *dir; + const osd::directory::entry *dir; while ((dir = path.next()) != nullptr) if (core_filename_ends_with(dir->name, ".ini") && parseopen(dir->name)) diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index 4e243f8ea8f..f48110dc6da 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -433,7 +433,7 @@ void menu_crosshair::populate() /* open a path to the crosshairs */ file_enumerator path(machine().options().crosshair_path()); - const osd_directory_entry *dir; + const osd::directory::entry *dir; /* reset search flags */ bool using_default = false; bool finished = false; diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 37ec5915885..87a8ebaec79 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -69,7 +69,7 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container *conta // check if there are available icons ui_globals::has_icons = false; file_enumerator path(moptions.icons_directory()); - const osd_directory_entry *dir; + const osd::directory::entry *dir; while ((dir = path.next()) != nullptr) { std::string src(dir->name); @@ -644,7 +644,7 @@ void menu_select_game::build_available_list() // open a path to the ROMs and find them in the array file_enumerator path(machine().options().media_path()); - const osd_directory_entry *dir; + const osd::directory::entry *dir; // iterate while we get new objects while ((dir = path.next()) != nullptr) diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 95f89bcb8dd..81c0bc97afe 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -608,7 +608,7 @@ void menu_select_software::build_software_list() } std::string searchstr, curpath; - const osd_directory_entry *dir; + const osd::directory::entry *dir; for (auto & elem : m_filter.swlist.name) { path_iterator path(machine().options().media_path()); @@ -621,9 +621,9 @@ void menu_select_software::build_software_list() while ((dir = fpath.next()) != nullptr) { std::string name; - if (dir->type == ENTTYPE_FILE) + if (dir->type == osd::directory::entry::entry_type::FILE) name = core_filename_extract_base(dir->name, true); - else if (dir->type == ENTTYPE_DIR && strcmp(dir->name, ".") != 0) + else if (dir->type == osd::directory::entry::entry_type::DIR && strcmp(dir->name, ".") != 0) name = dir->name; else continue; diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index e2ca4ff6d55..c947279a001 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -63,7 +63,7 @@ void simple_menu_select_game::build_driver_list() // open a path to the ROMs and find them in the array file_enumerator path(machine().options().media_path()); - const osd_directory_entry *dir; + const osd::directory::entry *dir; // iterate while we get new objects while ((dir = path.next()) != nullptr) diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 24d7b61fd2e..df941f3ceb7 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -1209,6 +1209,30 @@ void mame_ui_manager::draw_profiler(render_container *container) } +//------------------------------------------------- +// start_save_state +//------------------------------------------------- + +void mame_ui_manager::start_save_state() +{ + machine().pause(); + m_load_save_hold = true; + set_handler(UI_CALLBACK_TYPE_GENERAL, &mame_ui_manager::handler_load_save, (UINT32)LOADSAVE_SAVE); +} + + +//------------------------------------------------- +// start_load_state +//------------------------------------------------- + +void mame_ui_manager::start_load_state() +{ + machine().pause(); + m_load_save_hold = true; + set_handler(UI_CALLBACK_TYPE_GENERAL, &mame_ui_manager::handler_load_save, (UINT32)LOADSAVE_LOAD); +} + + //------------------------------------------------- // image_handler_ingame - execute display // callback function for each image device @@ -1386,18 +1410,14 @@ UINT32 mame_ui_manager::handler_ingame(render_container *container) // handle a save state request if (machine().ui_input().pressed(IPT_UI_SAVE_STATE)) { - machine().pause(); - m_load_save_hold = true; - set_handler(UI_CALLBACK_TYPE_GENERAL, &mame_ui_manager::handler_load_save, (UINT32)LOADSAVE_SAVE); + start_save_state(); return LOADSAVE_SAVE; } // handle a load state request if (machine().ui_input().pressed(IPT_UI_LOAD_STATE)) { - machine().pause(); - m_load_save_hold = true; - set_handler(UI_CALLBACK_TYPE_GENERAL, &mame_ui_manager::handler_load_save, (UINT32)LOADSAVE_LOAD); + start_load_state(); return LOADSAVE_LOAD; } diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index 982200d0556..d02e9dd2037 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -236,6 +236,8 @@ public: void draw_timecode_counter(render_container *container); void draw_timecode_total(render_container *container); void draw_profiler(render_container *container); + void start_save_state(); + void start_load_state(); // print the game info string into a buffer std::string &game_info_astring(std::string &str); diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp index 1e4fb6dd293..3322c1152cc 100644 --- a/src/lib/util/zippath.cpp +++ b/src/lib/util/zippath.cpp @@ -37,9 +37,9 @@ class zippath_directory public: zippath_directory() : returned_parent(false) - , directory(nullptr) + , directory() , called_zip_first(false) - , zipfile(nullptr) + , zipfile() , returned_dirlist() { } @@ -48,11 +48,11 @@ public: /** @brief true to returned parent. */ bool returned_parent; /** @brief The returned entry. */ - osd_directory_entry returned_entry; + osd::directory::entry returned_entry; /* specific to normal directories */ /** @brief Pathname of the directory. */ - osd_directory *directory; + osd::directory::ptr directory; /* specific to ZIP directories */ /** @brief true to called zip first. */ @@ -70,7 +70,7 @@ public: FUNCTION PROTOTYPES ***************************************************************************/ -static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpath, osd_dir_entry_type &type); +static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpath, osd::directory::entry::entry_type &type); static bool is_zip_file(std::string const &path); static bool is_zip_file_separator(char c); static bool is_7z_file(std::string const &path); @@ -341,7 +341,7 @@ osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core archive_file::error ziperr; archive_file::ptr zip; int header; - osd_dir_entry_type entry_type; + osd::directory::entry::entry_type entry_type; int len; /* first, set up the two types of paths */ @@ -616,7 +616,7 @@ static char next_path_char(std::string const &s, std::string::size_type &pos) -------------------------------------------------*/ /** - * @fn static const zip_file_header *zippath_find_sub_path(archive_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::directory::entry::entry_type *type) * * @brief Zippath find sub path. * @@ -627,7 +627,7 @@ static char next_path_char(std::string const &s, std::string::size_type &pos) * @return null if it fails, else a zip_file_header*. */ -static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpath, osd_dir_entry_type &type) +static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpath, osd::directory::entry::entry_type &type) { for (int header = zipfile.first_file(); header >= 0; header = zipfile.next_file()) { @@ -644,18 +644,18 @@ static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpa { if (!c1) { - type = zipfile.current_is_directory() ? ENTTYPE_DIR : ENTTYPE_FILE; + type = zipfile.current_is_directory() ? osd::directory::entry::entry_type::DIR : osd::directory::entry::entry_type::FILE; return header; } else if ((c1 == '/') || (i <= 1U)) { - type = ENTTYPE_DIR; + type = osd::directory::entry::entry_type::DIR; return header; } } } - type = ENTTYPE_NONE; + type = osd::directory::entry::entry_type::NONE; return -1; } @@ -667,7 +667,7 @@ static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpa -------------------------------------------------*/ /** - * @fn static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, archive_file *&zipfile, std::string &newpath) + * @fn static osd_file::error zippath_resolve(const char *path, osd::directory::entry::entry_type &entry_type, archive_file *&zipfile, std::string &newpath) * * @brief Zippath resolve. * @@ -679,17 +679,17 @@ static int zippath_find_sub_path(archive_file &zipfile, std::string const &subpa * @return A osd_file::error. */ -static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath) +static osd_file::error zippath_resolve(const char *path, osd::directory::entry::entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath) { newpath.clear(); // be conservative - entry_type = ENTTYPE_NONE; + entry_type = osd::directory::entry::entry_type::NONE; zipfile.reset(); std::string apath(path); std::string apath_trimmed; - osd_dir_entry_type current_entry_type; + osd::directory::entry::entry_type current_entry_type; bool went_up = false; do { @@ -701,7 +701,7 @@ static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &ent apath_trimmed = apath; // stat the path - std::unique_ptr current_entry(osd_stat(apath_trimmed), &osd_free); + auto current_entry = osd_stat(apath_trimmed); // did we find anything? if (current_entry) @@ -712,20 +712,20 @@ static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &ent else { // if we have not found the file or directory, go up - current_entry_type = ENTTYPE_NONE; + current_entry_type = osd::directory::entry::entry_type::NONE; went_up = true; std::string parent; apath = zippath_parent(parent, apath.c_str()); } } - while ((current_entry_type == ENTTYPE_NONE) && !is_root(apath.c_str())); + while ((current_entry_type == osd::directory::entry::entry_type::NONE) && !is_root(apath.c_str())); // if we did not find anything, then error out - if (current_entry_type == ENTTYPE_NONE) + if (current_entry_type == osd::directory::entry::entry_type::NONE) return osd_file::error::NOT_FOUND; // is this file a ZIP file? - if ((current_entry_type == ENTTYPE_FILE) && + if ((current_entry_type == osd::directory::entry::entry_type::FILE) && ((is_zip_file(apath_trimmed) && (archive_file::open_zip(apath_trimmed, zipfile) == archive_file::error::NONE)) || (is_7z_file(apath_trimmed) && (archive_file::open_7z(apath_trimmed, zipfile) == archive_file::error::NONE)))) { @@ -736,7 +736,7 @@ static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &ent // this was a true ZIP path - attempt to identify the type of path zippath_find_sub_path(*zipfile, newpath, current_entry_type); - if (current_entry_type == ENTTYPE_NONE) + if (current_entry_type == osd::directory::entry::entry_type::NONE) return osd_file::error::NOT_FOUND; } else @@ -785,13 +785,13 @@ osd_file::error zippath_opendir(const char *path, zippath_directory **directory) goto done; } /* resolve the path */ - osd_dir_entry_type entry_type; + osd::directory::entry::entry_type entry_type; err = zippath_resolve(path, entry_type, result->zipfile, result->zipprefix); if (err != osd_file::error::NONE) goto done; /* we have to be a directory */ - if (entry_type != ENTTYPE_DIR) + if (entry_type != osd::directory::entry::entry_type::DIR) { err = osd_file::error::NOT_FOUND; goto done; @@ -801,7 +801,7 @@ osd_file::error zippath_opendir(const char *path, zippath_directory **directory) if (!result->zipfile) { /* a conventional directory */ - result->directory = osd_opendir(path); + result->directory = osd::directory::open(path); if (!result->directory) { err = osd_file::error::FAILURE; @@ -840,7 +840,7 @@ done: void zippath_closedir(zippath_directory *directory) { if (directory->directory != nullptr) - osd_closedir(directory->directory); + directory->directory.reset(); if (directory->zipfile != nullptr) directory->zipfile.reset(); @@ -901,18 +901,18 @@ static const char *get_relative_path(zippath_directory const &directory) -------------------------------------------------*/ /** - * @fn const osd_directory_entry *zippath_readdir(zippath_directory *directory) + * @fn const osd::directory::entry *zippath_readdir(zippath_directory *directory) * * @brief Zippath readdir. * * @param [in,out] directory If non-null, pathname of the directory. * - * @return null if it fails, else an osd_directory_entry*. + * @return null if it fails, else an osd::directory::entry*. */ -const osd_directory_entry *zippath_readdir(zippath_directory *directory) +const osd::directory::entry *zippath_readdir(zippath_directory *directory) { - const osd_directory_entry *result = nullptr; + const osd::directory::entry *result = nullptr; if (!directory->returned_parent) { @@ -920,7 +920,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) directory->returned_parent = true; memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = ".."; - directory->returned_entry.type = ENTTYPE_DIR; + directory->returned_entry.type = osd::directory::entry::entry_type::DIR; result = &directory->returned_entry; } else if (directory->directory) @@ -928,7 +928,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) /* a normal directory read */ do { - result = osd_readdir(directory->directory); + result = directory->directory->read(); } while (result && (!strcmp(result->name, ".") || !strcmp(result->name, ".."))); @@ -937,7 +937,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) { /* copy; but change the entry type */ directory->returned_entry = *result; - directory->returned_entry.type = ENTTYPE_DIR; + directory->returned_entry.type = osd::directory::entry::entry_type::DIR; result = &directory->returned_entry; } } @@ -983,7 +983,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) /* ...and return it */ memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = directory->returned_dirlist.front().c_str(); - directory->returned_entry.type = ENTTYPE_DIR; + directory->returned_entry.type = osd::directory::entry::entry_type::DIR; result = &directory->returned_entry; } } @@ -992,7 +992,7 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory) /* a real file */ memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = relpath; - directory->returned_entry.type = ENTTYPE_FILE; + directory->returned_entry.type = osd::directory::entry::entry_type::FILE; directory->returned_entry.size = directory->zipfile->current_uncompressed_length(); result = &directory->returned_entry; } diff --git a/src/lib/util/zippath.h b/src/lib/util/zippath.h index 274852268bc..24325a89d68 100644 --- a/src/lib/util/zippath.h +++ b/src/lib/util/zippath.h @@ -58,7 +58,7 @@ osd_file::error zippath_opendir(const char *path, zippath_directory **directory) void zippath_closedir(zippath_directory *directory); /* reads a directory entry */ -const osd_directory_entry *zippath_readdir(zippath_directory *directory); +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); diff --git a/src/osd/modules/file/posixdir.cpp b/src/osd/modules/file/posixdir.cpp new file mode 100644 index 00000000000..d08d6869c6c --- /dev/null +++ b/src/osd/modules/file/posixdir.cpp @@ -0,0 +1,293 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb +//============================================================ +// +// sdldir.c - SDL core directory access functions +// +// SDLMAME by Olivier Galibert and R. Belmont +// +//============================================================ + + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifdef __linux__ +#ifndef __USE_LARGEFILE64 +#define __USE_LARGEFILE64 +#endif +#ifndef __USE_BSD +#define __USE_BSD +#endif +#endif + +#ifdef WIN32 +#define _FILE_OFFSET_BITS 64 +#endif + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__bsdi__) && !defined(__DragonFly__) +#ifdef _XOPEN_SOURCE +#if _XOPEN_SOURCE < 500 +#undef _XOPEN_SOURCE +#endif +#endif +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif +#endif + +#undef _POSIX_C_SOURCE // to get DT_xxx on OS X + + +#include "osdcore.h" +#include "modules/lib/osdlib.h" +#include "util/strformat.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +namespace osd { +namespace { +//============================================================ +// CONSTANTS +//============================================================ + +#if defined(WIN32) +constexpr char PATHSEPCH = '\\'; +constexpr char INVPATHSEPCH = '/'; +#else +constexpr char PATHSEPCH = '/'; +constexpr char INVPATHSEPCH = '\\'; +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(EMSCRIPTEN) || defined(__ANDROID__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) +using sdl_dirent = struct dirent; +using sdl_stat = struct stat; +#define sdl_readdir readdir +#define sdl_stat_fn stat +#else +using sdl_dirent = struct dirent64; +using sdl_stat = struct stat64; +#define sdl_readdir readdir64 +#define sdl_stat_fn stat64 +#endif + +#define HAS_DT_XXX (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)) + + + +//============================================================ +// TYPE DEFINITIONS +//============================================================ + +class posix_directory : public osd::directory +{ +public: + posix_directory(); + virtual ~posix_directory() override; + + virtual const entry *read() override; + + bool open(std::string const &dirname); + +private: + typedef std::unique_ptr dir_ptr; + + entry m_entry; + sdl_dirent *m_data; + dir_ptr m_fd; + std::string m_path; +}; + + +//============================================================ +// posix_directory::~posix_directory +//============================================================ + +posix_directory::posix_directory() + : m_entry() + , m_data(nullptr) + , m_fd(nullptr, &::closedir) + , m_path() +{ +} + + +//============================================================ +// posix_directory::~posix_directory +//============================================================ + +posix_directory::~posix_directory() +{ +} + + +//============================================================ +// posix_directory::read +//============================================================ + +const osd::directory::entry *posix_directory::read() +{ + m_data = sdl_readdir(m_fd.get()); + if (!m_data) + return nullptr; + + m_entry.name = m_data->d_name; + + sdl_stat st; + bool stat_err(0 > sdl_stat_fn(util::string_format("%s%c%s", m_path, PATHSEPCH, m_data->d_name).c_str(), &st)); + +#if HAS_DT_XXX + switch (m_data->d_type) + { + case DT_DIR: + m_entry.type = entry::entry_type::DIR; + break; + case DT_REG: + m_entry.type = entry::entry_type::FILE; + break; + case DT_LNK: + if (stat_err) + m_entry.type = entry::entry_type::OTHER; + else if (S_ISDIR(st.st_mode)) + m_entry.type = entry::entry_type::DIR; + else + m_entry.type = entry::entry_type::FILE; + break; + default: + m_entry.type = entry::entry_type::OTHER; + } +#else + if (stat_err) + m_entry.type = entry::entry_type::OTHER; + else if (S_ISDIR(st.st_mode)) + m_entry.type = entry::entry_type::DIR; + else + m_entry.type = entry::entry_type::FILE; +#endif + m_entry.size = stat_err ? 0 : std::uint64_t(std::make_unsigned_t(st.st_size)); + m_entry.last_modified = std::chrono::system_clock::from_time_t(st.st_mtime); + return &m_entry; +} + + +//============================================================ +// posix_directory::open +//============================================================ + +bool posix_directory::open(std::string const &dirname) +{ + assert(!m_fd); + + osd_subst_env(m_path, dirname); + m_fd.reset(::opendir(m_path.c_str())); + return bool(m_fd); +} + +} // anonymous namespace + + +//============================================================ +// osd::directory::open +//============================================================ + +directory::ptr directory::open(std::string const &dirname) +{ + ptr dir; + try { dir.reset(new posix_directory); } + catch (...) { return nullptr; } + + if (!dir->open(dirname)) + return nullptr; + + return dir; +} + +} // namespace osd + + +//============================================================ +// osd_subst_env +//============================================================ + +void osd_subst_env(std::string &dst, std::string const &src) +{ + std::string result, var; + auto start = src.begin(); + + // a leading tilde expands as $HOME + if ((src.end() != start) && ('~' == *start)) + { + char const *const home = std::getenv("HOME"); + if (home) + { + ++start; + if ((src.end() == start) || (osd::PATHSEPCH == *start)) + result.append(home); + else + result.push_back('~'); + } + } + + while (src.end() != start) + { + // find $ marking start of environment variable or end of string + auto it = start; + while ((src.end() != it) && ('$' != *it)) ++it; + if (start != it) result.append(start, it); + start = it; + + if (src.end() != start) + { + start = ++it; + if ((src.end() != start) && ('{' == *start)) + { + start = ++it; + for (++it; (src.end() != it) && ('}' != *it); ++it) { } + if (src.end() == it) + { + result.append("${").append(start, it); + start = it; + } + else + { + var.assign(start, it); + start = ++it; + const char *const exp = std::getenv(var.c_str()); + if (exp) + result.append(exp); + else + fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); + } + } + else if ((src.end() != start) && (('_' == *start) || std::isalnum(*start))) + { + for (++it; (src.end() != it) && (('_' == *it) || std::isalnum(*it)); ++it) { } + var.assign(start, it); + start = it; + const char *const exp = std::getenv(var.c_str()); + if (exp) + result.append(exp); + else + fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); + } + else + { + result.push_back('$'); + } + } + } + + dst = std::move(result); +} diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp index 8c3d2860060..8b8dc004da0 100644 --- a/src/osd/modules/file/posixfile.cpp +++ b/src/osd/modules/file/posixfile.cpp @@ -14,8 +14,13 @@ #endif #ifdef __linux__ +#ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif +#ifndef __USE_BSD +#define __USE_BSD +#endif +#endif #ifdef WIN32 #define _FILE_OFFSET_BITS 64 @@ -337,7 +342,7 @@ int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UIN // osd_stat //============================================================ -osd_directory_entry *osd_stat(const std::string &path) +std::unique_ptr osd_stat(const std::string &path) { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) struct stat st; @@ -350,13 +355,18 @@ osd_directory_entry *osd_stat(const std::string &path) // create an osd_directory_entry; be sure to make sure that the caller can // free all resources by just freeing the resulting osd_directory_entry - osd_directory_entry *const result = reinterpret_cast(osd_malloc_array(sizeof(osd_directory_entry) + path.length() + 1)); + osd::directory::entry *result; + try { result = reinterpret_cast(::operator new(sizeof(*result) + path.length() + 1)); } + catch (...) { return nullptr; } + new (result) osd::directory::entry; + std::strcpy(reinterpret_cast(result) + sizeof(*result), path.c_str()); result->name = reinterpret_cast(result) + sizeof(*result); - result->type = S_ISDIR(st.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE; + result->type = S_ISDIR(st.st_mode) ? osd::directory::entry::entry_type::DIR : osd::directory::entry::entry_type::FILE; result->size = std::uint64_t(std::make_unsigned_t(st.st_size)); + result->last_modified = std::chrono::system_clock::from_time_t(st.st_mtime); - return result; + return std::unique_ptr(result); } diff --git a/src/osd/modules/file/windir.cpp b/src/osd/modules/file/windir.cpp new file mode 100644 index 00000000000..e6eecfab4a2 --- /dev/null +++ b/src/osd/modules/file/windir.cpp @@ -0,0 +1,154 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +//============================================================ +// +// windir.c - Win32 OSD core directory access functions +// +//============================================================ + +// standard windows headers +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +// MAME headers +#include "osdcore.h" + +// MAMEOS headers +#include "strconv.h" +#include "winutil.h" + +// standard C headers +#include +#include +#include +#include + + +namespace osd { +namespace { +//============================================================ +// TYPE DEFINITIONS +//============================================================ + +class win_directory : public directory +{ +public: + win_directory(); + virtual ~win_directory() override; + + virtual const entry *read() override; + + bool open(std::string const &dirname); + +private: + HANDLE m_find; // handle to the finder + bool m_is_first; // true if this is the first entry + entry m_entry; // current entry's data + WIN32_FIND_DATA m_data; // current raw data +}; + +//============================================================ +// win_directory::win_directory +//============================================================ + +win_directory::win_directory() + : m_find(INVALID_HANDLE_VALUE) + , m_is_first(true) +{ + std::memset(&m_data, 0, sizeof(m_data)); +} + + +//============================================================ +// win_directory::~win_directory +//============================================================ + +win_directory::~win_directory() +{ + // free any data associated + if (m_entry.name != nullptr) + osd_free((void *)m_entry.name); + if (m_find != INVALID_HANDLE_VALUE) + FindClose(m_find); +} + + +//============================================================ +// win_directory::read +//============================================================ + +const directory::entry *win_directory::read() +{ + // if we've previously allocated a name, free it now + if (m_entry.name != nullptr) + { + osd_free((void *)m_entry.name); + m_entry.name = nullptr; + } + + // if this isn't the first file, do a find next + if (!m_is_first) + { + if (!FindNextFile(m_find, &m_data)) + return nullptr; + } + m_is_first = false; + + // extract the data + m_entry.name = utf8_from_tstring(m_data.cFileName); + m_entry.type = win_attributes_to_entry_type(m_data.dwFileAttributes); + m_entry.size = m_data.nFileSizeLow | (std::uint64_t(m_data.nFileSizeHigh) << 32); + m_entry.last_modified = win_time_point_from_filetime(&m_data.ftLastWriteTime); + return (m_entry.name != nullptr) ? &m_entry : nullptr; +} + + +//============================================================ +// win_directory::open +//============================================================ + +bool win_directory::open(std::string const &dirname) +{ + assert(m_find == INVALID_HANDLE_VALUE); + + // convert the path to TCHARs + std::unique_ptr const t_dirname(tstring_from_utf8(dirname.c_str()), &osd_free); + if (!t_dirname) + return false; + + // append \*.* to the directory name + auto const dirfilter_size = _tcslen(t_dirname.get()) + 5; + std::unique_ptr dirfilter; + try { dirfilter.reset(new TCHAR[dirfilter_size]); } + catch (...) { return false; } + _sntprintf(dirfilter.get(), dirfilter_size, TEXT("%s\\*.*"), t_dirname.get()); + + // attempt to find the first file + m_find = FindFirstFileEx(dirfilter.get(), FindExInfoStandard, &m_data, FindExSearchNameMatch, nullptr, 0); + if (m_find == INVALID_HANDLE_VALUE) + return false; +} + +} // anonymous namespace + + +//============================================================ +// osd::directory::open +//============================================================ + +directory::ptr directory::open(std::string const &dirname) +{ + // allocate memory to hold the osd_tool_directory structure + ptr dir; + try { dir.reset(new win_directory()); } + catch (...) { return nullptr; } + + if (!dir->open(dirname)) + return false; + + return dir; +} + +} // namesapce osd diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp index 9b6ecdc0535..c304259b915 100644 --- a/src/osd/modules/file/winfile.cpp +++ b/src/osd/modules/file/winfile.cpp @@ -354,7 +354,7 @@ int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UIN // osd_stat //============================================================ -osd_directory_entry *osd_stat(const std::string &path) +std::unique_ptr osd_stat(const std::string &path) { // convert the path to TCHARs std::unique_ptr const t_path(tstring_from_utf8(path.c_str()), &osd_free); @@ -379,17 +379,20 @@ osd_directory_entry *osd_stat(const std::string &path) FindClose(find); } - // create an osd_directory_entry; be sure to make sure that the caller can - // free all resources by just freeing the resulting osd_directory_entry - osd_directory_entry *const result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + path.length() + 1); - if (!result) - return nullptr; + // create an osd::directory::entry; be sure to make sure that the caller can + // free all resources by just freeing the resulting osd::directory::entry + osd::directory::entry *result; + try { result = reinterpret_cast(::operator new(sizeof(*result) + path.length() + 1)); } + catch (...) { return nullptr; } + new (result) osd::directory::entry; + strcpy(((char *) result) + sizeof(*result), path.c_str()); result->name = ((char *) result) + sizeof(*result); result->type = win_attributes_to_entry_type(find_data.dwFileAttributes); result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32); + result->last_modified = win_time_point_from_filetime(&find_data.ftLastWriteTime); - return result; + return std::unique_ptr(result); } diff --git a/src/osd/modules/render/bgfx/chainentryreader.cpp b/src/osd/modules/render/bgfx/chainentryreader.cpp index 39edd9f685c..278a795f6e7 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.cpp +++ b/src/osd/modules/render/bgfx/chainentryreader.cpp @@ -115,12 +115,12 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s directory_path += "/" + file_directory; } - osd_directory *directory = osd_opendir(directory_path.c_str()); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(directory_path); + if (directory) { - for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory)) + for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) { - if (entry->type == ENTTYPE_FILE) + if (entry->type == osd::directory::entry::entry_type::FILE) { std::string file(entry->name); std::string extension(".png"); @@ -159,8 +159,6 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s } } } - - osd_closedir(directory); } } } diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp index 34c891eb009..d4c59f9bb6a 100644 --- a/src/osd/modules/render/bgfx/chainmanager.cpp +++ b/src/osd/modules/render/bgfx/chainmanager.cpp @@ -91,12 +91,12 @@ void chain_manager::destroy_unloaded_chains() void chain_manager::find_available_chains(std::string root, std::string path) { - osd_directory *directory = osd_opendir((root + path).c_str()); + osd::directory::ptr directory = osd::directory::open(root + path); if (directory != nullptr) { - for (const osd_directory_entry *entry = osd_readdir(directory); entry != nullptr; entry = osd_readdir(directory)) + for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) { - if (entry->type == ENTTYPE_FILE) + if (entry->type == osd::directory::entry::entry_type::FILE) { std::string name(entry->name); std::string extension(".json"); @@ -114,7 +114,7 @@ void chain_manager::find_available_chains(std::string root, std::string path) } } } - else if (entry->type == ENTTYPE_DIR) + else if (entry->type == osd::directory::entry::entry_type::DIR) { std::string name = entry->name; if (!(name == "." || name == "..")) @@ -128,8 +128,6 @@ void chain_manager::find_available_chains(std::string root, std::string path) } } } - - osd_closedir(directory); } } diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h index c712b3fea8e..141f3db55d9 100644 --- a/src/osd/osdcore.h +++ b/src/osd/osdcore.h @@ -21,6 +21,7 @@ #include "osdcomm.h" +#include #include #include #include @@ -297,76 +298,66 @@ int osd_uchar_from_osdchar(UINT32 /* unicode_char */ *uchar, const char *osdchar DIRECTORY INTERFACES ***************************************************************************/ -/* types of directory entries that can be returned */ -enum osd_dir_entry_type +namespace osd { - ENTTYPE_NONE, - ENTTYPE_FILE, - ENTTYPE_DIR, - ENTTYPE_OTHER + // directory is an opaque type which represents an open directory + class directory + { + public: + typedef std::unique_ptr ptr; + + // osd::directory::entry contains basic information about a file when iterating through + // a directory + class entry + { + public: + enum class entry_type + { + NONE, + FILE, + DIR, + OTHER + }; + + const char * name; // name of the entry + entry_type type; // type of the entry + std::uint64_t size; // size of the entry + std::chrono::system_clock::time_point last_modified; // last modified time + }; + + // ----------------------------------------------------------------------------- + // osd::directory::open: open a directory for iteration + // + // Parameters: + // + // dirname - path to the directory in question + // + // Return value: + // + // upon success, this function should return an directory pointer + // which contains opaque data necessary to traverse the directory; on + // failure, this function should return nullptr + // ----------------------------------------------------------------------------- + static ptr open(std::string const &dirname); + + // ----------------------------------------------------------------------------- + // osd::directory::~directory: close an open directory + // ----------------------------------------------------------------------------- + virtual ~directory() { } + + // ----------------------------------------------------------------------------- + // osd::directory::read: return information about the next entry in the directory + // + // Return value: + // + // a constant pointer to an entry representing the current item + // in the directory, or nullptr, indicating that no more entries are + // present + // ----------------------------------------------------------------------------- + virtual const entry *read() = 0; + }; }; -/* osd_directory is an opaque type which represents an open directory */ -struct osd_directory; - -/* osd_directory_entry contains basic information about a file when iterating through */ -/* a directory */ -struct osd_directory_entry -{ - const char * name; /* name of the entry */ - osd_dir_entry_type type; /* type of the entry */ - UINT64 size; /* size of the entry */ -}; - - -/*----------------------------------------------------------------------------- - osd_opendir: open a directory for iteration - - Parameters: - - dirname - path to the directory in question - - Return value: - - upon success, this function should return an osd_directory pointer - which contains opaque data necessary to traverse the directory; on - failure, this function should return nullptr ------------------------------------------------------------------------------*/ -osd_directory *osd_opendir(const char *dirname); - - -/*----------------------------------------------------------------------------- - osd_readdir: return information about the next entry in the directory - - Parameters: - - dir - pointer to an osd_directory that was returned from a prior - call to osd_opendir - - Return value: - - a constant pointer to an osd_directory_entry representing the current item - in the directory, or nullptr, indicating that no more entries are - present ------------------------------------------------------------------------------*/ -const osd_directory_entry *osd_readdir(osd_directory *dir); - - -/*----------------------------------------------------------------------------- - osd_closedir: close an open directory for iteration - - Parameters: - - dir - pointer to an osd_directory that was returned from a prior - call to osd_opendir - - Return value: - - frees any allocated memory and resources associated with the open - directory ------------------------------------------------------------------------------*/ -void osd_closedir(osd_directory *dir); - /*----------------------------------------------------------------------------- osd_is_absolute_path: returns whether the specified path is absolute @@ -798,12 +789,11 @@ char *osd_get_clipboard_text(void); Return value: - an allocated pointer to an osd_directory_entry representing + an allocated pointer to an osd::directory::entry representing info on the path; even if the file does not exist. - free with osd_free() -----------------------------------------------------------------------------*/ -osd_directory_entry *osd_stat(std::string const &path); +std::unique_ptr osd_stat(std::string const &path); /*************************************************************************** PATH INTERFACES diff --git a/src/osd/sdl/sdldir.cpp b/src/osd/sdl/sdldir.cpp deleted file mode 100644 index fcae732ed53..00000000000 --- a/src/osd/sdl/sdldir.cpp +++ /dev/null @@ -1,316 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont -//============================================================ -// -// sdldir.c - SDL core directory access functions -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ - -#ifdef SDLMAME_WIN32 -#include "../windows/windir.cpp" -#else - -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif - -#ifdef SDLMAME_LINUX -#define __USE_LARGEFILE64 -#endif -#ifndef SDLMAME_BSD -#ifdef _XOPEN_SOURCE -#undef _XOPEN_SOURCE -#endif -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include - -//#include -#include -#include -#ifndef __USE_BSD -#define __USE_BSD // to get DT_xxx on Linux -#endif -#undef _POSIX_C_SOURCE // to get DT_xxx on OS X -#include - -#include "osdcore.h" -#include "modules/lib/osdlib.h" - -#if defined(SDLMAME_WIN32) -#define PATHSEPCH '\\' -#define INVPATHSEPCH '/' -#else -#define PATHSEPCH '/' -#define INVPATHSEPCH '\\' -#endif - -#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU) || defined(SDLMAME_EMSCRIPTEN) || defined(SDLMAME_ANDROID) -typedef struct dirent sdl_dirent; -typedef struct stat sdl_stat; -#define sdl_readdir readdir -#define sdl_stat_fn stat -#else -typedef struct dirent64 sdl_dirent; -typedef struct stat64 sdl_stat; -#define sdl_readdir readdir64 -#define sdl_stat_fn stat64 -#endif - -#define HAS_DT_XXX defined(SDLMAME_LINUX) || defined(SDLMAME_BSD) || defined(SDLMAME_DARWIN) - -struct osd_directory -{ - osd_directory_entry ent; - sdl_dirent *data; - DIR *fd; - char *path; -}; - -static char *build_full_path(const char *path, const char *file) -{ - char *ret = (char *) osd_malloc_array(strlen(path)+strlen(file)+2); - char *p = ret; - - strcpy(p, path); - p += strlen(path); - *p++ = PATHSEPCH; - strcpy(p, file); - return ret; -} - - -#if HAS_DT_XXX -static osd_dir_entry_type get_attributes_enttype(int attributes, char *path) -{ - switch ( attributes ) - { - case DT_DIR: - return ENTTYPE_DIR; - - case DT_REG: - return ENTTYPE_FILE; - - case DT_LNK: - { - struct stat s; - - if ( stat(path, &s) != 0 ) - return ENTTYPE_OTHER; - else - return S_ISDIR(s.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE; - } - - default: - return ENTTYPE_OTHER; - } -} -#else - -static osd_dir_entry_type get_attributes_stat(const char *file) -{ - sdl_stat st; - if(sdl_stat_fn(file, &st)) - return (osd_dir_entry_type) 0; - - if (S_ISDIR(st.st_mode)) - return ENTTYPE_DIR; - else - return ENTTYPE_FILE; -} -#endif - -static UINT64 osd_get_file_size(const char *file) -{ - sdl_stat st; - if(sdl_stat_fn(file, &st)) - return 0; - return st.st_size; -} - -//============================================================ -// osd_opendir -//============================================================ - -osd_directory *osd_opendir(const char *dirname) -{ - osd_directory *dir = nullptr; - char *tmpstr, *envstr; - int i, j; - - dir = (osd_directory *) osd_malloc(sizeof(osd_directory)); - if (dir) - { - memset(dir, 0, sizeof(osd_directory)); - dir->fd = nullptr; - } - - tmpstr = (char *) osd_malloc_array(strlen(dirname)+1); - strcpy(tmpstr, dirname); - - if (tmpstr[0] == '$') - { - envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); - - strcpy(envstr, tmpstr); - - i = 0; - while (envstr[i] != PATHSEPCH && envstr[i] != INVPATHSEPCH && envstr[i] != 0 && envstr[i] != '.') - { - i++; - } - - envstr[i] = '\0'; - - const char *envval = osd_getenv(&envstr[1]); - if (envval != nullptr) - { - j = strlen(envval) + strlen(tmpstr) + 1; - osd_free(tmpstr); - tmpstr = (char *) osd_malloc_array(j); - - // start with the value of $HOME - strcpy(tmpstr, envval); - // replace the null with a path separator again - envstr[i] = PATHSEPCH; - // append it - strcat(tmpstr, &envstr[i]); - } - else - fprintf(stderr, "Warning: osd_opendir environment variable %s not found.\n", envstr); - osd_free(envstr); - } - - dir->fd = opendir(tmpstr); - dir->path = tmpstr; - - if (dir && (dir->fd == nullptr)) - { - osd_free(dir->path); - osd_free(dir); - dir = nullptr; - } - - return dir; -} - - -//============================================================ -// osd_readdir -//============================================================ - -const osd_directory_entry *osd_readdir(osd_directory *dir) -{ - char *temp; - dir->data = sdl_readdir(dir->fd); - - if (dir->data == nullptr) - return nullptr; - - dir->ent.name = dir->data->d_name; - temp = build_full_path(dir->path, dir->data->d_name); - #if HAS_DT_XXX - dir->ent.type = get_attributes_enttype(dir->data->d_type, temp); - #else - dir->ent.type = get_attributes_stat(temp); - #endif - dir->ent.size = osd_get_file_size(temp); - osd_free(temp); - return &dir->ent; -} - - -//============================================================ -// osd_closedir -//============================================================ - -void osd_closedir(osd_directory *dir) -{ - if (dir->fd != nullptr) - closedir(dir->fd); - osd_free(dir->path); - osd_free(dir); -} - - -//============================================================ -// osd_subst_env -//============================================================ - -void osd_subst_env(std::string &dst, std::string const &src) -{ - std::string result, var; - auto start = src.begin(); - - // a leading tilde expands as $HOME - if ((src.end() != start) && ('~' == *start)) - { - char const *const home = std::getenv("HOME"); - if (home) - { - ++start; - if ((src.end() == start) || (PATHSEPCH == *start)) - result.append(home); - else - result.push_back('~'); - } - } - - while (src.end() != start) - { - // find $ marking start of environment variable or end of string - auto it = start; - while ((src.end() != it) && ('$' != *it)) ++it; - if (start != it) result.append(start, it); - start = it; - - if (src.end() != start) - { - start = ++it; - if ((src.end() != start) && ('{' == *start)) - { - start = ++it; - for (++it; (src.end() != it) && ('}' != *it); ++it) { } - if (src.end() == it) - { - result.append("${").append(start, it); - start = it; - } - else - { - var.assign(start, it); - start = ++it; - const char *const exp = std::getenv(var.c_str()); - if (exp) - result.append(exp); - else - fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); - } - } - else if ((src.end() != start) && (('_' == *start) || std::isalnum(*start))) - { - for (++it; (src.end() != it) && (('_' == *it) || std::isalnum(*it)); ++it) { } - var.assign(start, it); - start = it; - const char *const exp = std::getenv(var.c_str()); - if (exp) - result.append(exp); - else - fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); - } - else - { - result.push_back('$'); - } - } - } - - dst = std::move(result); -} - -#endif diff --git a/src/osd/windows/windir.cpp b/src/osd/windows/windir.cpp deleted file mode 100644 index f7b7fd44c6a..00000000000 --- a/src/osd/windows/windir.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -//============================================================ -// -// windir.c - Win32 OSD core directory access functions -// -//============================================================ - -// standard windows headers -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -// standard C headers -#include -#include - -// MAME headers -#include "osdcore.h" - -// MAMEOS headers -#include "strconv.h" -#include "winutil.h" - - -//============================================================ -// TYPE DEFINITIONS -//============================================================ - -struct osd_directory -{ - HANDLE find; // handle to the finder - int is_first; // TRUE if this is the first entry - osd_directory_entry entry; // current entry's data - WIN32_FIND_DATA data; // current raw data -}; - - - -//============================================================ -// osd_opendir -//============================================================ - -osd_directory *osd_opendir(const char *dirname) -{ - osd_directory *dir = nullptr; - TCHAR *t_dirname = nullptr; - TCHAR *dirfilter = nullptr; - size_t dirfilter_size; - - // allocate memory to hold the osd_tool_directory structure - dir = (osd_directory *)malloc(sizeof(*dir)); - if (dir == nullptr) - goto error; - memset(dir, 0, sizeof(*dir)); - - // initialize the structure - dir->find = INVALID_HANDLE_VALUE; - dir->is_first = TRUE; - - // convert the path to TCHARs - t_dirname = tstring_from_utf8(dirname); - if (t_dirname == nullptr) - goto error; - - // append \*.* to the directory name - dirfilter_size = _tcslen(t_dirname) + 5; - dirfilter = (TCHAR *)malloc(dirfilter_size * sizeof(*dirfilter)); - if (dirfilter == nullptr) - goto error; - _sntprintf(dirfilter, dirfilter_size, TEXT("%s\\*.*"), t_dirname); - - // attempt to find the first file - dir->find = FindFirstFileEx(dirfilter, FindExInfoStandard, &dir->data, FindExSearchNameMatch, nullptr, 0); - -error: - // cleanup - if (t_dirname != nullptr) - osd_free(t_dirname); - if (dirfilter != nullptr) - free(dirfilter); - if (dir != nullptr && dir->find == INVALID_HANDLE_VALUE) - { - free(dir); - dir = nullptr; - } - return dir; -} - - -//============================================================ -// osd_readdir -//============================================================ - -const osd_directory_entry *osd_readdir(osd_directory *dir) -{ - // if we've previously allocated a name, free it now - if (dir->entry.name != nullptr) - { - osd_free((void *)dir->entry.name); - dir->entry.name = nullptr; - } - - // if this isn't the first file, do a find next - if (!dir->is_first) - { - if (!FindNextFile(dir->find, &dir->data)) - return nullptr; - } - - // otherwise, just use the data we already had - else - dir->is_first = FALSE; - - // extract the data - dir->entry.name = utf8_from_tstring(dir->data.cFileName); - dir->entry.type = win_attributes_to_entry_type(dir->data.dwFileAttributes); - dir->entry.size = dir->data.nFileSizeLow | ((UINT64) dir->data.nFileSizeHigh << 32); - return (dir->entry.name != nullptr) ? &dir->entry : nullptr; -} - - -//============================================================ -// osd_closedir -//============================================================ - -void osd_closedir(osd_directory *dir) -{ - // free any data associated - if (dir->entry.name != nullptr) - osd_free((void *)dir->entry.name); - if (dir->find != INVALID_HANDLE_VALUE) - FindClose(dir->find); - free(dir); -} diff --git a/src/osd/windows/winutil.cpp b/src/osd/windows/winutil.cpp index 880e9aa7a06..3ec2314068e 100644 --- a/src/osd/windows/winutil.cpp +++ b/src/osd/windows/winutil.cpp @@ -23,14 +23,26 @@ // win_attributes_to_entry_type //============================================================ -osd_dir_entry_type win_attributes_to_entry_type(DWORD attributes) +osd::directory::entry::entry_type win_attributes_to_entry_type(DWORD attributes) { if (attributes == 0xFFFFFFFF) - return ENTTYPE_NONE; + return osd::directory::entry::entry_type::NONE; else if (attributes & FILE_ATTRIBUTE_DIRECTORY) - return ENTTYPE_DIR; + return osd::directory::entry::entry_type::DIR; else - return ENTTYPE_FILE; + return osd::directory::entry::entry_type::FILE; +} + + + +//============================================================ +// win_time_point_from_filetime +//============================================================ + +std::chrono::system_clock::time_point win_time_point_from_filetime(LPFILETIME file_time) +{ + return std::chrono::system_clock::time_point(std::chrono::system_clock::duration( + (static_cast<__int64>(file_time->dwHighDateTime) << 32) | file_time->dwLowDateTime)); } diff --git a/src/osd/windows/winutil.h b/src/osd/windows/winutil.h index 2598a920864..57470bf1372 100644 --- a/src/osd/windows/winutil.h +++ b/src/osd/windows/winutil.h @@ -12,9 +12,11 @@ #include "osdcore.h" #include #include +#include // Shared code -osd_dir_entry_type win_attributes_to_entry_type(DWORD attributes); +osd::directory::entry::entry_type win_attributes_to_entry_type(DWORD attributes); +std::chrono::system_clock::time_point win_time_point_from_filetime(LPFILETIME file_time); BOOL win_is_gui_application(void); HMODULE WINAPI GetModuleHandleUni(); diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp index 641667b6342..0545da64c64 100644 --- a/src/tools/romcmp.cpp +++ b/src/tools/romcmp.cpp @@ -448,22 +448,20 @@ static void printname(const fileinfo *file1,const fileinfo *file2,float score,in static int load_files(int i, int *found, const char *path) { - osd_directory *dir; - /* attempt to open as a directory first */ - dir = osd_opendir(path); - if (dir != nullptr) + auto dir = osd::directory::open(path); + if (dir) { - const osd_directory_entry *d; + const osd::directory::entry *d; /* load all files in directory */ - while ((d = osd_readdir(dir)) != nullptr) + while ((d = dir->read()) != nullptr) { const char *d_name = d->name; char buf[255+1]; sprintf(buf, "%s%c%s", path, PATH_DELIM, d_name); - if (d->type == ENTTYPE_FILE) + if (d->type == osd::directory::entry::entry_type::FILE) { UINT64 size = d->size; while (size && (size & 1) == 0) size >>= 1; @@ -484,7 +482,7 @@ static int load_files(int i, int *found, const char *path) } } } - osd_closedir(dir); + dir.reset(); } /* if not, try to open as a ZIP file */ diff --git a/src/tools/src2html.cpp b/src/tools/src2html.cpp index 38260a62879..9d89a7d220f 100644 --- a/src/tools/src2html.cpp +++ b/src/tools/src2html.cpp @@ -324,7 +324,7 @@ static int compare_list_entries(const void *p1, const void *p2) static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std::string &dstdir, std::string &tempheader, std::string &tempfooter) { - static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE }; + static const osd::directory::entry::entry_type typelist[] = { osd::directory::entry::entry_type::DIR, osd::directory::entry::entry_type::FILE }; // extract a normalized subpath std::string srcdir_subpath; @@ -344,10 +344,10 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: int result = 0; for (int entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++) { - osd_dir_entry_type entry_type = typelist[entindex]; + auto entry_type = typelist[entindex]; // open the directory and iterate through it - osd_directory *dir = osd_opendir(srcdir.c_str()); + auto dir = osd::directory::open(srcdir.c_str()); if (dir == nullptr) { result = 1; @@ -355,10 +355,10 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: } // build up the list of files - const osd_directory_entry *entry; + const osd::directory::entry *entry; int found = 0; list_entry *list = nullptr; - while ((entry = osd_readdir(dir)) != nullptr) + while ((entry = dir->read()) != nullptr) if (entry->type == entry_type && entry->name[0] != '.') { auto lentry = new list_entry; @@ -369,7 +369,7 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: } // close the directory - osd_closedir(dir); + dir.reset(); // skip if nothing found if (found == 0) @@ -398,7 +398,7 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: { // add a header if (curlist == list) - indexfile->printf("\t

%s

\n\t
    \n", (entry_type == ENTTYPE_DIR) ? "Directories" : "Files"); + indexfile->printf("\t

    %s

    \n\t
      \n", (entry_type == osd::directory::entry::entry_type::DIR) ? "Directories" : "Files"); // build the source filename std::string srcfile; @@ -406,7 +406,7 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: // if we have a file, output it std::string dstfile; - if (entry_type == ENTTYPE_FILE) + if (entry_type == osd::directory::entry::entry_type::FILE) { // make sure we care, first file_type type = FILE_TYPE_INVALID;