diff options
author | 2016-03-13 13:54:57 +1100 | |
---|---|---|
committer | 2016-03-14 18:55:00 +1100 | |
commit | 42fbb9c3967fcda37f2d9ae17d5796a79cf027b9 (patch) | |
tree | a43047ee00431e5e22bfc5f8f612ff775586e415 /src/osd/modules/file/stdfile.cpp | |
parent | 5fc27747031b6ed6f6c0582502098ebfb960be67 (diff) |
Make osd_file a polymorphic class that's held with smart pointers
Make avi_file a class that's held with smart pointers, encapsulate various AVI I/O structures
Make zip_file and _7z_file classes rather than having free functions everywhere
Hide zip/7z class implementation behind an interface, no longer need to call close() to send back to the cache
Don't dump as much crap in global namespace
Add solaris PTY implementation
Improve variable expansion for SDL OSD - supports ~/$FOO/${BAR} syntax
Rearrange stuff so the same things are in file module for all OSDs
Move file stuff into its own module
7z/zip open and destruct are still not thread-safe due to lack of interlocks around cache access
Directory functions still need to be moved to file module
SDL OSD may not initialise WinSock on Windows
Diffstat (limited to 'src/osd/modules/file/stdfile.cpp')
-rw-r--r-- | src/osd/modules/file/stdfile.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/osd/modules/file/stdfile.cpp b/src/osd/modules/file/stdfile.cpp new file mode 100644 index 00000000000..92920bba495 --- /dev/null +++ b/src/osd/modules/file/stdfile.cpp @@ -0,0 +1,251 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +//============================================================ +// +// minifile.c - Minimal core file access functions +// +//============================================================ + +#include "osdcore.h" + +#include <cassert> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <string> + +#include <stdio.h> // for fileno +#include <unistd.h> // for ftruncate + + +namespace { +class std_osd_file : public osd_file +{ +public: + + std_osd_file(FILE *f) : m_file(f) { assert(m_file); } + + //============================================================ + // osd_close + //============================================================ + + virtual ~std_osd_file() override + { + // close the file handle + if (m_file) std::fclose(m_file); + } + + //============================================================ + // osd_read + //============================================================ + + virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + { + // seek to the new location; note that most fseek implementations are limited to 32 bits + if (std::fseek(m_file, offset, SEEK_SET) < 0) + return error::FAILURE; + + // perform the read + std::size_t const count = std::fread(buffer, 1, length, m_file); + actual = count; + + return error::NONE; + } + + //============================================================ + // osd_write + //============================================================ + + virtual error write(const void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + { + // seek to the new location; note that most fseek implementations are limited to 32 bits + if (std::fseek(m_file, offset, SEEK_SET) < 0) + return error::FAILURE; + + // perform the write + std::size_t const count = std::fwrite(buffer, 1, length, m_file); + actual = count; + + return error::NONE; + } + + //============================================================ + // osd_truncate + //============================================================ + + error truncate(std::uint64_t offset) override + { + return (ftruncate(fileno(m_file), offset) < 0) ? error::FAILURE : error::NONE; + } + + //============================================================ + // osd_fflush + //============================================================ + + virtual error flush() override + { + return (std::fflush(m_file) == EOF) ? error::FAILURE : error::NONE; + } + +private: + FILE *m_file; +}; + +} // anonymous namespace + + +//============================================================ +// osd_open +//============================================================ + +osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) +{ + // based on the flags, choose a mode + const char *mode; + if (openflags & OPEN_FLAG_WRITE) + { + if (openflags & OPEN_FLAG_READ) + mode = (openflags & OPEN_FLAG_CREATE) ? "w+b" : "r+b"; + else + mode = "wb"; + } + else if (openflags & OPEN_FLAG_READ) + mode = "rb"; + else + return error::INVALID_ACCESS; + + // open the file + FILE *const fileptr = std::fopen(path.c_str(), mode); + if (!fileptr) + return error::NOT_FOUND; + + // get the size -- note that most fseek/ftell implementations are limited to 32 bits + long length; + if ((std::fseek(fileptr, 0, SEEK_END) < 0) || + ((length = std::ftell(fileptr)) < 0) || + (std::fseek(fileptr, 0, SEEK_SET) < 0)) + { + std::fclose(fileptr); + return error::FAILURE; + } + + try + { + file = std::make_unique<std_osd_file>(fileptr); + filesize = std::int64_t(length); + return error::NONE; + } + catch (...) + { + std::fclose(fileptr); + return error::OUT_OF_MEMORY; + } +} + + +//============================================================ +// osd_openpty +//============================================================ + +osd_file::error osd_file::openpty(ptr &file, std::string &name) +{ + return error::FAILURE; +} + + +//============================================================ +// osd_rmfile +//============================================================ + +osd_file::error osd_file::remove(std::string const &filename) +{ + return (std::remove(filename.c_str()) < 0) ? error::FAILURE : error::NONE; +} + + +//============================================================ +// osd_get_physical_drive_geometry +//============================================================ + +int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps) +{ + // there is no standard way of doing this, so we always return FALSE, indicating + // that a given path is not a physical drive + return FALSE; +} + + +//============================================================ +// osd_uchar_from_osdchar +//============================================================ + +int osd_uchar_from_osdchar(UINT32 /* unicode_char */ *uchar, const char *osdchar, size_t count) +{ + // we assume a standard 1:1 mapping of characters to the first 256 unicode characters + *uchar = (UINT8)*osdchar; + return 1; +} + + +//============================================================ +// osd_stat +//============================================================ + +osd_directory_entry *osd_stat(const std::string &path) +{ + osd_directory_entry *result = 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 + result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + path.length() + 1); + strcpy((char *)(result + 1), path.c_str()); + result->name = (char *)(result + 1); + result->type = ENTTYPE_NONE; + result->size = 0; + + FILE *f = std::fopen(path.c_str(), "rb"); + if (f != nullptr) + { + std::fseek(f, 0, SEEK_END); + result->type = ENTTYPE_FILE; + result->size = std::ftell(f); + std::fclose(f); + } + return result; +} + + +//============================================================ +// osd_get_full_path +//============================================================ + +osd_file::error osd_get_full_path(std::string &dst, std::string const &path) +{ + // derive the full path of the file in an allocated string + // for now just fake it since we don't presume any underlying file system + dst = path; + + return osd_file::error::NONE; +} + + +//============================================================ +// osd_is_absolute_path +//============================================================ + +bool osd_is_absolute_path(std::string const &path) +{ + // assume no for everything + return false; +} + + +//============================================================ +// osd_get_volume_name +//============================================================ + +const char *osd_get_volume_name(int idx) +{ + // we don't expose volumes + return nullptr; +} |