mirror of https://github.com/stella-emu/stella.git
First pass at converting FSNode to std::filesystem.
This code is broken; do not attempt to use!
This commit is contained in:
parent
e253be49d5
commit
686a5e289d
|
@ -16,6 +16,7 @@
|
|||
//============================================================================
|
||||
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
|
||||
#include "SqliteDatabase.hxx"
|
||||
#include "Logger.hxx"
|
||||
|
@ -25,7 +26,8 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteDatabase::SqliteDatabase(const string& databaseDirectory,
|
||||
const string& databaseName)
|
||||
: myDatabaseFile{databaseDirectory + databaseName + ".sqlite3"}
|
||||
: myDatabaseFile{(std::filesystem::path(databaseDirectory) /
|
||||
(databaseName + ".sqlite3")).string()}
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,12 @@ void FSNode::setPath(const string& path)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FSNode& FSNode::operator/=(const string& path)
|
||||
{
|
||||
#if 0
|
||||
_fspath /= path;
|
||||
setFlags();
|
||||
|
||||
return *this;
|
||||
#else
|
||||
if (path != EmptyString)
|
||||
{
|
||||
string newPath = getPath();
|
||||
|
@ -60,6 +66,7 @@ FSNode& FSNode::operator/=(const string& path)
|
|||
}
|
||||
|
||||
return *this;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -232,8 +239,7 @@ const string& FSNode::getName() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FSNode::setName(const string& name)
|
||||
{
|
||||
if (_realNode)
|
||||
_realNode->setName(name);
|
||||
if (_realNode) _realNode->setName(name);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -251,6 +257,15 @@ string FSNode::getShortPath() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string FSNode::getNameWithExt(const string& ext) const
|
||||
{
|
||||
#if 1
|
||||
fs::path p = getName();
|
||||
if (ext != EmptyString)
|
||||
p.replace_extension(ext);
|
||||
else
|
||||
p.replace_extension();
|
||||
|
||||
return p.string();
|
||||
#else
|
||||
if (!_realNode)
|
||||
return EmptyString;
|
||||
|
||||
|
@ -260,6 +275,7 @@ string FSNode::getNameWithExt(const string& ext) const
|
|||
|
||||
pos = s.find_last_of('.');
|
||||
return (pos != string::npos) ? s.replace(pos, string::npos, ext) : s + ext;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -335,117 +351,47 @@ size_t FSNode::getSize() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNode::read(ByteBuffer& buffer, size_t size) const
|
||||
{
|
||||
size_t sizeRead = 0;
|
||||
|
||||
// File must actually exist
|
||||
if (!(exists() && isReadable()))
|
||||
throw runtime_error("File not found/readable");
|
||||
|
||||
// First let the private subclass attempt to open the file
|
||||
size_t sizeRead = 0;
|
||||
if (_realNode && (sizeRead = _realNode->read(buffer, size)) > 0)
|
||||
return sizeRead;
|
||||
|
||||
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||
std::ifstream in(getPath(), std::ios::binary);
|
||||
if (in)
|
||||
{
|
||||
in.seekg(0, std::ios::end);
|
||||
sizeRead = static_cast<size_t>(in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
if (sizeRead == 0)
|
||||
throw runtime_error("Zero-byte file");
|
||||
else if (size > 0) // If a requested size to read is provided, honour it
|
||||
sizeRead = std::min(sizeRead, size);
|
||||
|
||||
buffer = make_unique<uInt8[]>(sizeRead);
|
||||
in.read(reinterpret_cast<char*>(buffer.get()), sizeRead);
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/read error");
|
||||
|
||||
return sizeRead;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNode::read(stringstream& buffer) const
|
||||
{
|
||||
size_t sizeRead = 0;
|
||||
|
||||
// File must actually exist
|
||||
if (!(exists() && isReadable()))
|
||||
throw runtime_error("File not found/readable");
|
||||
|
||||
// First let the private subclass attempt to open the file
|
||||
size_t sizeRead = 0;
|
||||
if (_realNode && (sizeRead = _realNode->read(buffer)) > 0)
|
||||
return sizeRead;
|
||||
|
||||
// Otherwise, the default behaviour is to read from a normal C++ ifstream
|
||||
// and convert to a stringstream
|
||||
std::ifstream in(getPath());
|
||||
if (in)
|
||||
{
|
||||
in.seekg(0, std::ios::end);
|
||||
sizeRead = static_cast<size_t>(in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
if (sizeRead == 0)
|
||||
throw runtime_error("Zero-byte file");
|
||||
|
||||
buffer << in.rdbuf();
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/read error");
|
||||
|
||||
return sizeRead;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNode::write(const ByteBuffer& buffer, size_t size) const
|
||||
{
|
||||
size_t sizeWritten = 0;
|
||||
|
||||
// First let the private subclass attempt to open the file
|
||||
if (_realNode && (sizeWritten = _realNode->write(buffer, size)) > 0)
|
||||
return sizeWritten;
|
||||
|
||||
// Otherwise, the default behaviour is to write to a normal C++ ofstream
|
||||
std::ofstream out(getPath(), std::ios::binary);
|
||||
if (out)
|
||||
{
|
||||
out.write(reinterpret_cast<const char*>(buffer.get()), size);
|
||||
|
||||
out.seekp(0, std::ios::end);
|
||||
sizeWritten = static_cast<size_t>(out.tellp());
|
||||
out.seekp(0, std::ios::beg);
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/write error");
|
||||
|
||||
return sizeWritten;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNode::write(const stringstream& buffer) const
|
||||
{
|
||||
size_t sizeWritten = 0;
|
||||
|
||||
// First let the private subclass attempt to open the file
|
||||
if (_realNode && (sizeWritten = _realNode->write(buffer)) > 0)
|
||||
return sizeWritten;
|
||||
|
||||
// Otherwise, the default behaviour is to write to a normal C++ ofstream
|
||||
std::ofstream out(getPath());
|
||||
if (out)
|
||||
{
|
||||
out << buffer.rdbuf();
|
||||
|
||||
out.seekp(0, std::ios::end);
|
||||
sizeWritten = static_cast<size_t>(out.tellp());
|
||||
out.seekp(0, std::ios::beg);
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/write error");
|
||||
|
||||
return sizeWritten;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef FS_NODE_HXX
|
||||
#define FS_NODE_HXX
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
|
||||
#include "bspf.hxx"
|
||||
|
@ -34,6 +35,7 @@
|
|||
class FSNode;
|
||||
class AbstractFSNode;
|
||||
using AbstractFSNodePtr = shared_ptr<AbstractFSNode>;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
/**
|
||||
* List of multiple file system nodes. E.g. the contents of a given directory.
|
||||
|
@ -462,7 +464,7 @@ class AbstractFSNode
|
|||
* This method can throw exceptions, and should be used inside
|
||||
* a try-catch block.
|
||||
*/
|
||||
virtual size_t read(ByteBuffer& buffer, size_t size) const { return 0; }
|
||||
virtual size_t read(ByteBuffer& buffer, size_t size) const = 0;
|
||||
|
||||
/**
|
||||
* Read data (text format) into the given stream.
|
||||
|
@ -473,7 +475,7 @@ class AbstractFSNode
|
|||
* This method can throw exceptions, and should be used inside
|
||||
* a try-catch block.
|
||||
*/
|
||||
virtual size_t read(stringstream& buffer) const { return 0; }
|
||||
virtual size_t read(stringstream& buffer) const = 0;
|
||||
|
||||
/**
|
||||
* Write data (binary format) from the given buffer.
|
||||
|
@ -485,7 +487,7 @@ class AbstractFSNode
|
|||
* This method can throw exceptions, and should be used inside
|
||||
* a try-catch block.
|
||||
*/
|
||||
virtual size_t write(const ByteBuffer& buffer, size_t size) const { return 0; }
|
||||
virtual size_t write(const ByteBuffer& buffer, size_t size) const = 0;
|
||||
|
||||
/**
|
||||
* Write data (text format) from the given stream.
|
||||
|
@ -496,7 +498,7 @@ class AbstractFSNode
|
|||
* This method can throw exceptions, and should be used inside
|
||||
* a try-catch block.
|
||||
*/
|
||||
virtual size_t write(const stringstream& buffer) const { return 0; }
|
||||
virtual size_t write(const stringstream& buffer) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the last component of a given path.
|
||||
|
|
|
@ -37,7 +37,11 @@ FSNodePOSIX::FSNodePOSIX(const string& path, bool verify)
|
|||
// Expand '~' to the HOME environment variable
|
||||
if(_path[0] == '~')
|
||||
{
|
||||
#if defined(BSPF_WINDOWS)
|
||||
|
||||
#else
|
||||
const char* home = std::getenv("HOME");
|
||||
#endif
|
||||
if (home != nullptr)
|
||||
_path.replace(0, 1, home);
|
||||
}
|
||||
|
@ -49,7 +53,9 @@ FSNodePOSIX::FSNodePOSIX(const string& path, bool verify)
|
|||
_path = buf.data();
|
||||
}
|
||||
|
||||
_displayName = lastPathComponent(_path);
|
||||
_fspath = _path;
|
||||
_displayName = _fspath.filename();
|
||||
_path = _fspath.string();
|
||||
|
||||
if(verify)
|
||||
setFlags();
|
||||
|
@ -58,6 +64,34 @@ FSNodePOSIX::FSNodePOSIX(const string& path, bool verify)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FSNodePOSIX::setFlags()
|
||||
{
|
||||
#if 1
|
||||
// cerr << "_fspath: " << _fspath << endl;
|
||||
std::error_code ec;
|
||||
const auto s = fs::status(_fspath, ec);
|
||||
if (!ec)
|
||||
{
|
||||
const auto p = s.permissions();
|
||||
|
||||
_isValid = true;
|
||||
_isFile = fs::is_regular_file(s);
|
||||
_isDirectory = fs::is_directory(s);
|
||||
_isReadable = (p & (fs::perms::owner_read |
|
||||
fs::perms::group_read |
|
||||
fs::perms::others_read)) != fs::perms::none;
|
||||
_isWriteable = (p & (fs::perms::owner_write |
|
||||
fs::perms::group_write |
|
||||
fs::perms::others_write)) != fs::perms::none;
|
||||
// cerr << "_isValid: " << _isValid << endl
|
||||
// << "_isFile: " << _isFile << endl
|
||||
// << "_isDirectory: " << _isDirectory << endl
|
||||
// << "_isReadable: " << _isReadable << endl
|
||||
// << "_isWriteable: " << _isWriteable << endl
|
||||
// << endl;
|
||||
}
|
||||
else
|
||||
_isValid = _isFile = _isDirectory = _isReadable = _isWriteable = false;
|
||||
|
||||
#else
|
||||
struct stat st;
|
||||
|
||||
_isValid = (0 == stat(_path.c_str(), &st));
|
||||
|
@ -72,13 +106,18 @@ void FSNodePOSIX::setFlags()
|
|||
}
|
||||
else
|
||||
_isDirectory = _isFile = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string FSNodePOSIX::getShortPath() const
|
||||
{
|
||||
// If the path starts with the home directory, replace it with '~'
|
||||
#if defined(BSPF_WINDOWS)
|
||||
|
||||
#else
|
||||
const char* env_home = std::getenv("HOME");
|
||||
#endif
|
||||
const string& home = env_home != nullptr ? env_home : EmptyString;
|
||||
|
||||
if(home != EmptyString && BSPF::startsWithIgnoreCase(_path, home))
|
||||
|
@ -101,6 +140,7 @@ bool FSNodePOSIX::hasParent() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FSNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode) const
|
||||
{
|
||||
cerr << "getChildren: " << _path << endl;
|
||||
assert(_isDirectory);
|
||||
|
||||
DIR* dirp = opendir(_path.c_str());
|
||||
|
@ -187,6 +227,91 @@ size_t FSNodePOSIX::getSize() const
|
|||
return (stat(_path.c_str(), &st) == 0) ? st.st_size : 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNodePOSIX::read(ByteBuffer& buffer, size_t size) const
|
||||
{
|
||||
size_t sizeRead = 0;
|
||||
std::ifstream in(getPath(), std::ios::binary);
|
||||
if (in)
|
||||
{
|
||||
in.seekg(0, std::ios::end);
|
||||
sizeRead = static_cast<size_t>(in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
if (sizeRead == 0)
|
||||
throw runtime_error("Zero-byte file");
|
||||
else if (size > 0) // If a requested size to read is provided, honour it
|
||||
sizeRead = std::min(sizeRead, size);
|
||||
|
||||
buffer = make_unique<uInt8[]>(sizeRead);
|
||||
in.read(reinterpret_cast<char*>(buffer.get()), sizeRead);
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/read error");
|
||||
|
||||
return sizeRead;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNodePOSIX::read(stringstream& buffer) const
|
||||
{
|
||||
size_t sizeRead = 0;
|
||||
std::ifstream in(getPath());
|
||||
if (in)
|
||||
{
|
||||
in.seekg(0, std::ios::end);
|
||||
sizeRead = static_cast<size_t>(in.tellg());
|
||||
in.seekg(0, std::ios::beg);
|
||||
|
||||
if (sizeRead == 0)
|
||||
throw runtime_error("Zero-byte file");
|
||||
|
||||
buffer << in.rdbuf();
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/read error");
|
||||
|
||||
return sizeRead;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNodePOSIX::write(const ByteBuffer& buffer, size_t size) const
|
||||
{
|
||||
size_t sizeWritten = 0;
|
||||
std::ofstream out(getPath(), std::ios::binary);
|
||||
if (out)
|
||||
{
|
||||
out.write(reinterpret_cast<const char*>(buffer.get()), size);
|
||||
|
||||
out.seekp(0, std::ios::end);
|
||||
sizeWritten = static_cast<size_t>(out.tellp());
|
||||
out.seekp(0, std::ios::beg);
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/write error");
|
||||
|
||||
return sizeWritten;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNodePOSIX::write(const stringstream& buffer) const
|
||||
{
|
||||
size_t sizeWritten = 0;
|
||||
std::ofstream out(getPath());
|
||||
if (out)
|
||||
{
|
||||
out << buffer.rdbuf();
|
||||
|
||||
out.seekp(0, std::ios::end);
|
||||
sizeWritten = static_cast<size_t>(out.tellp());
|
||||
out.seekp(0, std::ios::beg);
|
||||
}
|
||||
else
|
||||
throw runtime_error("File open/write error");
|
||||
|
||||
return sizeWritten;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FSNodePOSIX::makeDir()
|
||||
{
|
||||
|
|
|
@ -39,9 +39,11 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Implementation of the Stella file system API based on POSIX (for Linux and macOS)
|
||||
* Implementation of the Stella filesystem API for regular files,
|
||||
* based on the std::filesystem API in C++17.
|
||||
*
|
||||
* Parts of this class are documented in the base interface class, AbstractFSNode.
|
||||
* Parts of this class are documented in the base interface classes,
|
||||
* AbstractFSNode and FSNode. See those classes for more information.
|
||||
*/
|
||||
class FSNodePOSIX : public AbstractFSNode
|
||||
{
|
||||
|
@ -60,7 +62,7 @@ class FSNodePOSIX : public AbstractFSNode
|
|||
*/
|
||||
explicit FSNodePOSIX(const string& path, bool verify = true);
|
||||
|
||||
bool exists() const override { return access(_path.c_str(), F_OK) == 0; }
|
||||
bool exists() const override { return fs::exists(_fspath); }
|
||||
const string& getName() const override { return _displayName; }
|
||||
void setName(const string& name) override { _displayName = name; }
|
||||
const string& getPath() const override { return _path; }
|
||||
|
@ -68,21 +70,25 @@ class FSNodePOSIX : public AbstractFSNode
|
|||
bool hasParent() const override;
|
||||
bool isDirectory() const override { return _isDirectory; }
|
||||
bool isFile() const override { return _isFile; }
|
||||
bool isReadable() const override { return access(_path.c_str(), R_OK) == 0; }
|
||||
bool isWritable() const override { return access(_path.c_str(), W_OK) == 0; }
|
||||
bool isReadable() const override { return _isReadable; }
|
||||
bool isWritable() const override { return _isWriteable; }
|
||||
bool makeDir() override;
|
||||
bool rename(const string& newfile) override;
|
||||
|
||||
size_t getSize() const override;
|
||||
size_t read(ByteBuffer& buffer, size_t size) const override;
|
||||
size_t read(stringstream& buffer) const override;
|
||||
size_t write(const ByteBuffer& buffer, size_t size) const override;
|
||||
size_t write(const stringstream& buffer) const override;
|
||||
|
||||
bool getChildren(AbstractFSList& list, ListMode mode) const override;
|
||||
AbstractFSNodePtr getParent() const override;
|
||||
|
||||
protected:
|
||||
string _path;
|
||||
string _displayName;
|
||||
bool _isValid{true};
|
||||
bool _isFile{false};
|
||||
bool _isDirectory{true};
|
||||
fs::path _fspath;
|
||||
string _path, _displayName;
|
||||
bool _isValid{false}, _isFile{false}, _isDirectory{false},
|
||||
_isReadable{false}, _isWriteable{false};
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue