VFS - Ported from old LW code
This commit is contained in:
parent
68716e9193
commit
bb94169a31
4 changed files with 694 additions and 0 deletions
150
include/ebcl/VFS.hh
Normal file
150
include/ebcl/VFS.hh
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/* VIRTUAL FILE SYSTEM ********************************************************/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _H_EBCL_VFS
|
||||||
|
#define _H_EBCL_VFS
|
||||||
|
|
||||||
|
#include <ebcl/Sets.hh>
|
||||||
|
#include <ebcl/Strings.hh>
|
||||||
|
#include <ebcl/Streams.hh>
|
||||||
|
#include <ebcl/Files.hh>
|
||||||
|
#include <ebcl/Registration.hh>
|
||||||
|
namespace ebcl {
|
||||||
|
|
||||||
|
|
||||||
|
/*= DRIVERS ==================================================================*/
|
||||||
|
|
||||||
|
class A_VFSDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~A_VFSDriver( ) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialisation and shutdown methods, called by the main VFS code.
|
||||||
|
* These do nothing by default.
|
||||||
|
*/
|
||||||
|
virtual bool init( );
|
||||||
|
virtual void shutdown( );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: the main VFS code will NEVER pass anything but an absolute
|
||||||
|
* path to the methods below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Get the type of an entry in the VFS */
|
||||||
|
virtual E_FSEntryType typeOf( T_FSPath const& path ) = 0;
|
||||||
|
|
||||||
|
/* Checks that a path exists */
|
||||||
|
bool exists( T_FSPath const& path );
|
||||||
|
|
||||||
|
/* List entries matching a VFS path. The method should return true if
|
||||||
|
* the path was found by the driver and was a directory, or false if
|
||||||
|
* it wasn't.
|
||||||
|
*/
|
||||||
|
virtual bool list( T_FSPath const& path ,
|
||||||
|
T_Set< T_FSPath >& values ) = 0;
|
||||||
|
|
||||||
|
/* Try reading from a VFS file. Returns an owning pointer that's either
|
||||||
|
* null if the path in question couldn't be found (or wasn't a file)
|
||||||
|
* or that refers to some unspecified input stream.
|
||||||
|
*/
|
||||||
|
virtual OP_InputStream read( T_FSPath const& path ) = 0;
|
||||||
|
|
||||||
|
/* Try opening a path as an actual file. If the driver doesn't support
|
||||||
|
* this, or if it cannot open the file for whatever reason, this should
|
||||||
|
* return null (which is what the default implementation does).
|
||||||
|
*/
|
||||||
|
virtual OP_File file( T_FSPath const& path );
|
||||||
|
};
|
||||||
|
M_ABSTRACT_POINTERS( VFSDriver );
|
||||||
|
|
||||||
|
|
||||||
|
/*= VFS FILESYSTEM DRIVER ====================================================*/
|
||||||
|
|
||||||
|
/* A driver that allows the VFS to access a part of the actual filesystem. */
|
||||||
|
class T_VFSFilesystemDriver : public A_VFSDriver
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
T_FSPath root_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
T_VFSFilesystemDriver( ) = delete;
|
||||||
|
T_VFSFilesystemDriver( T_VFSFilesystemDriver const& ) = delete;
|
||||||
|
T_VFSFilesystemDriver( T_VFSFilesystemDriver&& ) noexcept = delete;
|
||||||
|
|
||||||
|
explicit T_VFSFilesystemDriver( T_FSPath const& root );
|
||||||
|
|
||||||
|
T_FSPath const& root( ) const;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool init( ) override;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
E_FSEntryType typeOf( T_FSPath const& path ) override;
|
||||||
|
bool list( T_FSPath const& path , T_Set< T_FSPath >& values ) override;
|
||||||
|
|
||||||
|
OP_InputStream read( T_FSPath const& path ) override;
|
||||||
|
OP_File file( T_FSPath const& path ) override;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T_String getFullPath( T_FSPath const& path ) const;
|
||||||
|
T_Buffer< char > getOSPath( T_FSPath const& path ) const;
|
||||||
|
};
|
||||||
|
M_CLASS_POINTERS( VFSFilesystemDriver );
|
||||||
|
|
||||||
|
|
||||||
|
/*= VFS CORE =================================================================*/
|
||||||
|
|
||||||
|
class X_VFSInitialisationFailure : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
X_VFSInitialisationFailure( );
|
||||||
|
};
|
||||||
|
|
||||||
|
class T_VFS : public A_PrivateImplementation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Initialise the VFS, using the specified RW directory
|
||||||
|
T_VFS( T_FSPath const& userDir );
|
||||||
|
|
||||||
|
T_VFS( ) = delete;
|
||||||
|
T_VFS( T_VFS const& ) = delete;
|
||||||
|
T_VFS( T_VFS&& ) = delete;
|
||||||
|
|
||||||
|
// Add a new VFS driver
|
||||||
|
T_RegisteredItem addDriver( OP_VFSDriver&& driver );
|
||||||
|
template<
|
||||||
|
typename DriverType ,
|
||||||
|
typename... ArgTypes
|
||||||
|
>
|
||||||
|
T_RegisteredItem addDriver( ArgTypes&& ... arguments );
|
||||||
|
|
||||||
|
// Read-only access methods.
|
||||||
|
E_FSEntryType typeOf( T_FSPath const& path ) const;
|
||||||
|
bool list( T_FSPath const& path , T_Array< T_FSPath >& output ) const;
|
||||||
|
OP_InputStream read( T_FSPath const& path ) const;
|
||||||
|
OP_File file( T_FSPath const& path ) const;
|
||||||
|
|
||||||
|
// Read/write access for the user directory.
|
||||||
|
OP_File file( T_FSPath const& path , E_FileMode mode ) const;
|
||||||
|
OP_OutputStream write( T_FSPath const& path ) const;
|
||||||
|
bool mkdir( T_FSPath const& path ) const;
|
||||||
|
bool rmdir( T_FSPath const& path ) const;
|
||||||
|
bool rm( T_FSPath const& path ) const;
|
||||||
|
bool move( T_FSPath const& from ,
|
||||||
|
T_FSPath const& to ) const;
|
||||||
|
|
||||||
|
// Path style for the VFS
|
||||||
|
static constexpr T_FSPathStyle Style( ) noexcept;
|
||||||
|
};
|
||||||
|
M_CLASS_POINTERS( VFS );
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
#endif // _H_EBCL_VFS
|
||||||
|
#include <ebcl/inline/VFS.hh>
|
60
include/ebcl/inline/VFS.hh
Normal file
60
include/ebcl/inline/VFS.hh
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/* VIRTUAL FILE SYSTEM - INLINE CODE ******************************************/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _H_EBCL_INLINE_VFS
|
||||||
|
#define _H_EBCL_INLINE_VFS
|
||||||
|
#include <ebcl/VFS.hh>
|
||||||
|
namespace ebcl {
|
||||||
|
|
||||||
|
|
||||||
|
/*= A_VFSDriver ==============================================================*/
|
||||||
|
|
||||||
|
inline A_VFSDriver::~A_VFSDriver( )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
inline bool A_VFSDriver::exists( T_FSPath const& path )
|
||||||
|
{
|
||||||
|
const auto et( typeOf( path ) );
|
||||||
|
return et != E_FSEntryType::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_VFSFilesystemDriver ====================================================*/
|
||||||
|
|
||||||
|
inline T_FSPath const& T_VFSFilesystemDriver::root( ) const
|
||||||
|
{
|
||||||
|
return root_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= X_VFSInitialisationFailure ===============================================*/
|
||||||
|
|
||||||
|
inline X_VFSInitialisationFailure::X_VFSInitialisationFailure( )
|
||||||
|
: std::runtime_error( "unable to initialise VFS" )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_VFS ====================================================================*/
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename DriverType ,
|
||||||
|
typename... ArgTypes
|
||||||
|
>
|
||||||
|
inline T_RegisteredItem T_VFS::addDriver( ArgTypes&& ... arguments )
|
||||||
|
{
|
||||||
|
return addDriver( NewOwned< DriverType >(
|
||||||
|
std::forward< ArgTypes >( arguments ) ... ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr T_FSPathStyle T_VFS::Style( ) noexcept
|
||||||
|
{
|
||||||
|
return T_FSPathStyle{ true , false ,
|
||||||
|
T_Flags< E_FSPathSeparator >{
|
||||||
|
E_FSPathSeparator::SLASH ,
|
||||||
|
E_FSPathSeparator::BACKSLASH } };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // _H_EBCL_INLINE_VFS
|
483
src/VFS.cc
Normal file
483
src/VFS.cc
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/* VIRTUAL FILE SYSTEM ********************************************************/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#include <ebcl/VFS.hh>
|
||||||
|
using namespace ebcl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*= A_VFSDriver ==============================================================*/
|
||||||
|
|
||||||
|
bool A_VFSDriver::init( )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void A_VFSDriver::shutdown( )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
OP_File A_VFSDriver::file( T_FSPath const& )
|
||||||
|
{
|
||||||
|
return OP_File( );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_VFSFilesystemDriver ====================================================*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define C_SEPARATOR_ '\\'
|
||||||
|
#else
|
||||||
|
# define C_SEPARATOR_ '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
T_VFSFilesystemDriver::T_VFSFilesystemDriver(
|
||||||
|
T_FSPath const& path )
|
||||||
|
{
|
||||||
|
assert( path.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
assert( path.isValid( ) );
|
||||||
|
root_ = path.canonical( );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool T_VFSFilesystemDriver::init( )
|
||||||
|
{
|
||||||
|
const auto type{ Filesystem::TypeOf( root_ ) };
|
||||||
|
return type == E_FSEntryType::DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
E_FSEntryType T_VFSFilesystemDriver::typeOf(
|
||||||
|
T_FSPath const& path )
|
||||||
|
{
|
||||||
|
return Filesystem::TypeOf( root_ + path );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFSFilesystemDriver::list(
|
||||||
|
T_FSPath const& path ,
|
||||||
|
T_Set< T_FSPath >& values )
|
||||||
|
{
|
||||||
|
T_Array< T_String > items;
|
||||||
|
if ( ! Filesystem::List( root_ + path , items ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto const& item : items ) {
|
||||||
|
if ( item == "." || item == ".." ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const T_FSPath iPath{ path + item };
|
||||||
|
if ( !iPath.isValid( ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
values.add( iPath );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_InputStream T_VFSFilesystemDriver::read(
|
||||||
|
T_FSPath const& path )
|
||||||
|
{
|
||||||
|
if ( typeOf( path ) != E_FSEntryType::FILE ) {
|
||||||
|
return OP_InputStream( );
|
||||||
|
} else {
|
||||||
|
auto f( file( path ) );
|
||||||
|
if ( f ) {
|
||||||
|
return NewOwned< T_FileInputStream >( std::move( f ) );
|
||||||
|
} else {
|
||||||
|
return OP_InputStream( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_File T_VFSFilesystemDriver::file(
|
||||||
|
T_FSPath const& path )
|
||||||
|
{
|
||||||
|
if ( typeOf( path ) != E_FSEntryType::FILE ) {
|
||||||
|
return OP_File( );
|
||||||
|
}
|
||||||
|
return NewOwned< T_File >( getFullPath( path ) , E_FileMode::READ_ONLY );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
T_String T_VFSFilesystemDriver::getFullPath(
|
||||||
|
T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
return ( root_ + path ).toString( );
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Buffer< char > T_VFSFilesystemDriver::getOSPath(
|
||||||
|
T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
return getFullPath( path ).toOSString( );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_VFSUserDirectory_ ======================================================*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class T_VFSUserDirectory_ : public T_VFSFilesystemDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit T_VFSUserDirectory_( T_FSPath const& base );
|
||||||
|
|
||||||
|
bool init( ) override;
|
||||||
|
|
||||||
|
OP_File file( T_FSPath const& path ) override;
|
||||||
|
OP_File file( T_FSPath const& path , E_FileMode mode );
|
||||||
|
OP_OutputStream write( T_FSPath const& path );
|
||||||
|
bool mkdir( T_FSPath const& path ) const;
|
||||||
|
bool rmdir( T_FSPath const& path ) const;
|
||||||
|
bool rm( T_FSPath const& path ) const;
|
||||||
|
bool move( T_FSPath const& from , T_FSPath const& to ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
T_VFSUserDirectory_::T_VFSUserDirectory_(
|
||||||
|
T_FSPath const& base )
|
||||||
|
: T_VFSFilesystemDriver( base )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool T_VFSUserDirectory_::init( )
|
||||||
|
{
|
||||||
|
if ( T_VFSFilesystemDriver::init( ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try creating the user directory
|
||||||
|
T_FSPath const& r( root( ) );
|
||||||
|
return Filesystem::MkDirFull( r );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
OP_File T_VFSUserDirectory_::file( T_FSPath const& path )
|
||||||
|
{
|
||||||
|
return T_VFSFilesystemDriver::file( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_File T_VFSUserDirectory_::file( T_FSPath const& path , E_FileMode mode )
|
||||||
|
{
|
||||||
|
if ( mode == E_FileMode::READ_ONLY ) {
|
||||||
|
return file( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto fp( getFullPath( path ) );
|
||||||
|
const auto ft( Filesystem::TypeOf( fp ) );
|
||||||
|
if ( ft != E_FSEntryType::FILE && ft != E_FSEntryType::NONE ) {
|
||||||
|
return OP_File( );
|
||||||
|
}
|
||||||
|
return NewOwned< T_File >( fp , mode );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
OP_OutputStream T_VFSUserDirectory_::write( T_FSPath const& path )
|
||||||
|
{
|
||||||
|
auto f( file( path , E_FileMode::OVERWRITE ) );
|
||||||
|
if ( f ) {
|
||||||
|
return NewOwned< T_FileOutputStream >( std::move( f ) );
|
||||||
|
} else {
|
||||||
|
return OP_OutputStream( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool T_VFSUserDirectory_::mkdir( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
return Filesystem::MkDirFull( root( ) + path );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFSUserDirectory_::rmdir( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
return Filesystem::RmDir( root( ) + path );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFSUserDirectory_::rm( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
return Filesystem::Rm( root( ) + path );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFSUserDirectory_::move(
|
||||||
|
T_FSPath const& from ,
|
||||||
|
T_FSPath const& to ) const
|
||||||
|
{
|
||||||
|
return Filesystem::Move( root( ) + from , root( ) + to );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_VFSPrivate_ ============================================================*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct T_VFSPrivate_
|
||||||
|
{
|
||||||
|
T_RegisteredItem::SP_Unregister unregisterFunction_{
|
||||||
|
NewShared< T_RegisteredItem::F_Unregister >(
|
||||||
|
[this]( void* data ) {
|
||||||
|
auto const n( drivers_.size( ) );
|
||||||
|
for ( uint32_t i = 0 ; i < n ; i ++ ) {
|
||||||
|
auto& p( drivers_[ i ] );
|
||||||
|
if ( p.get( ) == data ) {
|
||||||
|
p->shutdown( );
|
||||||
|
drivers_.removeSwap( i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) };
|
||||||
|
OP_VFSFilesystemDriver userDir_;
|
||||||
|
T_Array< OP_VFSDriver > drivers_{ 16 };
|
||||||
|
|
||||||
|
static T_String findUserDir( );
|
||||||
|
void initUserDir( T_FSPath const& dir );
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void T_VFSPrivate_::initUserDir( T_FSPath const& dir )
|
||||||
|
{
|
||||||
|
assert( !userDir_ );
|
||||||
|
userDir_ = NewOwned< T_VFSUserDirectory_ >( dir );
|
||||||
|
if ( !userDir_->init( ) ) {
|
||||||
|
throw X_VFSInitialisationFailure( );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*= T_VFS ====================================================================*/
|
||||||
|
|
||||||
|
T_VFS::T_VFS( T_FSPath const& userDir )
|
||||||
|
: A_PrivateImplementation( new T_VFSPrivate_( ) )
|
||||||
|
{
|
||||||
|
assert( userDir.style( ) == T_FSPathStyle::System( ) );
|
||||||
|
p< T_VFSPrivate_ >( ).initUserDir( userDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
T_RegisteredItem T_VFS::addDriver( OP_VFSDriver&& driver )
|
||||||
|
{
|
||||||
|
assert( driver );
|
||||||
|
const bool ok( driver->init( ) );
|
||||||
|
if ( ok ) {
|
||||||
|
auto& pi( p< T_VFSPrivate_ >( ) );
|
||||||
|
void* const ptr( driver.get( ) );
|
||||||
|
pi.drivers_.add( std::move( driver ) );
|
||||||
|
return T_RegisteredItem( pi.unregisterFunction_ , ptr );
|
||||||
|
}
|
||||||
|
return T_RegisteredItem( );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
E_FSEntryType T_VFS::typeOf(
|
||||||
|
T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return E_FSEntryType::NONE;
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
auto& pi( p< T_VFSPrivate_ >( ) );
|
||||||
|
E_FSEntryType rv( pi.userDir_->typeOf( np ) );
|
||||||
|
const auto nd( pi.drivers_.size( ) );
|
||||||
|
for ( uint32_t i = nd ; i != 0 && rv == E_FSEntryType::NONE ; i -- ) {
|
||||||
|
rv = pi.drivers_[ i - 1 ]->typeOf( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFS::list(
|
||||||
|
T_FSPath const& path ,
|
||||||
|
T_Array< T_FSPath >& output ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
// Get the result set
|
||||||
|
auto& pi( p< T_VFSPrivate_ >( ) );
|
||||||
|
T_Set< T_FSPath > values{ UseTag< IndexBacked<> >( ) };
|
||||||
|
bool rv{ pi.userDir_->list( np , values ) };
|
||||||
|
const auto nd( pi.drivers_.size( ) );
|
||||||
|
for ( uint32_t i = nd ; i != 0 ; i -- ) {
|
||||||
|
rv = pi.drivers_[ i - 1 ]->list( np , values ) || rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to array and sort
|
||||||
|
const auto nr{ values.size( ) };
|
||||||
|
output.clear( );
|
||||||
|
for ( auto i = 0u ; i < nr ; i ++ ) {
|
||||||
|
output.add( values[ i ] );
|
||||||
|
}
|
||||||
|
output.sort( );
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_InputStream T_VFS::read( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
auto& pi( p< T_VFSPrivate_ >( ) );
|
||||||
|
OP_InputStream rv{ pi.userDir_->read( np ) };
|
||||||
|
const auto nd{ pi.drivers_.size( ) };
|
||||||
|
for ( uint32_t i = nd ; i != 0 && !rv ; i -- ) {
|
||||||
|
rv = pi.drivers_[ i - 1 ]->read( np );
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_File T_VFS::file( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
auto& pi{ p< T_VFSPrivate_ >( ) };
|
||||||
|
OP_File rv{ pi.userDir_->file( np ) };
|
||||||
|
const auto nd{ pi.drivers_.size( ) };
|
||||||
|
for ( uint32_t i = nd ; i != 0 && !rv ; i -- ) {
|
||||||
|
rv = pi.drivers_[ i - 1 ]->file( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
OP_File T_VFS::file(
|
||||||
|
T_FSPath const& path ,
|
||||||
|
const E_FileMode mode ) const
|
||||||
|
{
|
||||||
|
if ( mode == E_FileMode::READ_ONLY ) {
|
||||||
|
return file( path );
|
||||||
|
} else {
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
return dynamic_cast< T_VFSUserDirectory_* >(
|
||||||
|
p< T_VFSPrivate_ >( ).userDir_.get( ) )
|
||||||
|
->file( np , mode );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OP_OutputStream T_VFS::write( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
return dynamic_cast< T_VFSUserDirectory_* >(
|
||||||
|
p< T_VFSPrivate_ >( ).userDir_.get( )
|
||||||
|
)->write( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFS::mkdir( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
return dynamic_cast< T_VFSUserDirectory_* >(
|
||||||
|
p< T_VFSPrivate_ >( ).userDir_.get( )
|
||||||
|
)->mkdir( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFS::rmdir( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
return dynamic_cast< T_VFSUserDirectory_* >(
|
||||||
|
p< T_VFSPrivate_ >( ).userDir_.get( )
|
||||||
|
)->rmdir( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFS::rm( T_FSPath const& path ) const
|
||||||
|
{
|
||||||
|
assert( path.style( ) == Style( ) );
|
||||||
|
if ( ! path.isValid( ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto np{ path.isAbsolute( )
|
||||||
|
? path.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + path ).canonical( ) };
|
||||||
|
|
||||||
|
return dynamic_cast< T_VFSUserDirectory_* >(
|
||||||
|
p< T_VFSPrivate_ >( ).userDir_.get( )
|
||||||
|
)->rm( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool T_VFS::move( T_FSPath const& from , T_FSPath const& to ) const
|
||||||
|
{
|
||||||
|
assert( from.style( ) == Style( ) );
|
||||||
|
assert( to.style( ) == Style( ) );
|
||||||
|
if ( ! ( from.isValid( ) && to.isValid( ) ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto nFrom{ from.isAbsolute( )
|
||||||
|
? from.canonical( )
|
||||||
|
: ( T_FSPath( "/" , Style( ) ) + from ).canonical( ) };
|
||||||
|
if ( nFrom.components( ).size( ) == 0 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_FSPath nTo;
|
||||||
|
if ( to.isAbsolute( ) ) {
|
||||||
|
nTo = to.canonical( );
|
||||||
|
} else {
|
||||||
|
nTo = ( nFrom + T_FSPath( ".." ) + to ).canonical( );
|
||||||
|
}
|
||||||
|
if ( nTo.components( ).size( ) == 0 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamic_cast< T_VFSUserDirectory_* >(
|
||||||
|
p< T_VFSPrivate_ >( ).userDir_.get( ) )
|
||||||
|
->move( nFrom , nTo );
|
||||||
|
}
|
|
@ -16,4 +16,5 @@ LIB_SOURCES = \
|
||||||
src/Strings.cc \
|
src/Strings.cc \
|
||||||
src/TemplateInstantiation.cc \
|
src/TemplateInstantiation.cc \
|
||||||
src/Utilities.cc \
|
src/Utilities.cc \
|
||||||
|
src/VFS.cc \
|
||||||
# END
|
# END
|
||||||
|
|
Loading…
Reference in a new issue