Files
tenmon/3rdparty/include/pcl/File.h
T
2022-04-12 08:17:18 +02:00

2416 lines
78 KiB
C++

// ____ ______ __
// / __ \ / ____// /
// / /_/ // / / /
// / ____// /___ / /___ PixInsight Class Library
// /_/ \____//_____/ PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/File.h - Released 2022-03-12T18:59:29Z
// ----------------------------------------------------------------------------
// This file is part of the PixInsight Class Library (PCL).
// PCL is a multiplatform C++ framework for development of PixInsight modules.
//
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
//
// Redistribution and use in both source and binary forms, with or without
// modification, is permitted provided that the following conditions are met:
//
// 1. All redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. All redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
// of their contributors, may be used to endorse or promote products derived
// from this software without specific prior written permission. For written
// permission, please contact info@pixinsight.com.
//
// 4. All products derived from this software, in any form whatsoever, must
// reproduce the following acknowledgment in the end-user documentation
// and/or other materials provided with the product:
//
// "This product is based on software from the PixInsight project, developed
// by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
//
// Alternatively, if that is where third-party acknowledgments normally
// appear, this acknowledgment must be reproduced in the product itself.
//
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------
#ifndef __PCL_File_h
#define __PCL_File_h
/// \file pcl/File.h
#include <pcl/Defs.h>
#include <pcl/Diagnostics.h>
#include <pcl/ByteArray.h>
#include <pcl/Exception.h>
#include <pcl/Flags.h>
#include <pcl/StringList.h>
#ifndef __PCL_FILE_DONT_REMOVE_PREVIOUS_DECLARATION
/*
* Remove conflicting identifiers from Win32 SDK headers.
*/
#ifdef CreateFile
#undef CreateFile
#endif
#ifdef CopyFile
#undef CopyFile
#endif
#ifdef MoveFile
#undef MoveFile
#endif
#ifdef CreateDirectory
#undef CreateDirectory
#endif
#ifdef RemoveDirectory
#undef RemoveDirectory
#endif
#endif // !__PCL_FILE_DONT_REMOVE_PREVIOUS_DECLARATION
namespace pcl
{
// ----------------------------------------------------------------------------
/*!
* \defgroup file_utilities File Support Classes and Functions
*/
// ----------------------------------------------------------------------------
/*!
* \namespace pcl::FileMode
* \brief File access, share and opening/creation modes.
*
* <table border="1" cellpadding="4" cellspacing="0">
* <tr><td>FileMode::Read</td> <td>Read access enabled</td></tr>
* <tr><td>FileMode::Write</td> <td>Write access enabled</td></tr>
* <tr><td>FileMode::AccessMode</td> <td>Mask to isolate read/write flags</td></tr>
* <tr><td>FileMode::ShareRead</td> <td>(Windows only) Sharing for reading enabled</td></tr>
* <tr><td>FileMode::ShareWrite</td> <td>(Windows only) Sharing for writing enabled</td></tr>
* <tr><td>FileMode::ShareMode</td> <td>(Windows only) Mask to isolate share read/write flags</td></tr>
* <tr><td>FileMode::Open</td> <td>Open an existing file</td></tr>
* <tr><td>FileMode::Create</td> <td>Create a new file or truncate an existing file</td></tr>
* <tr><td>FileMode::OpenMode</td> <td>Mask to isolate open/creation flags</td></tr>
* </table>
*
* \ingroup file_utilities
*/
namespace FileMode
{
enum mask_type
{
Zero = 0x00000000,
/*
* Access mode
*/
Read = 0x00000001,
Write = 0x00000002,
AccessMode = 0x0000000F,
/*
* Share mode (Windows only)
*/
ShareRead = 0x00000010,
ShareWrite = 0x00000020,
ShareMode = 0x000000F0,
/*
* Open/create mode
*/
Open = 0x00000100,
Create = 0x00000200,
OpenMode = 0x00000F00
};
}
/*!
* \class pcl::FileModes
* \brief A combination of file access, share and opening/creation mode flags
* \ingroup file_utilities
*/
typedef Flags<FileMode::mask_type> FileModes;
// ----------------------------------------------------------------------------
/*!
* \namespace pcl::SeekMode
* \brief File seek modes.
*
* <table border="1" cellpadding="4" cellspacing="0">
* <tr><td>SeekMode::FromBegin</td> <td>Move file pointer relative to the beginning of the file</td></tr>
* <tr><td>SeekMode::FromCurrent</td> <td>Move file pointer from the current position</td></tr>
* <tr><td>SeekMode::FromEnd</td> <td>Move file pointer relative to the end of the file</td></tr>
* </table>
*
* \ingroup file_utilities
*/
namespace SeekMode
{
enum value_type
{
FromBegin, // Move relative to the beginning of the file
FromCurrent, // Move from current position
FromEnd, // Move relative to the end of the file
NumberOfSeekModes
};
}
// ----------------------------------------------------------------------------
/*!
* \namespace pcl::FileAttribute
* \brief File attributes
*
* <table border="1" cellpadding="4" cellspacing="0">
* <tr><td colspan="2"><b>File type</b></td></tr>
* <tr><td>FileAttribute::Block</td> <td>Block special</td></tr>
* <tr><td>FileAttribute::Character</td> <td>Character special</td></tr>
* <tr><td>FileAttribute::FIFO</td> <td>FIFO special</td></tr>
* <tr><td>FileAttribute::Regular</td> <td>Regular file</td></tr>
* <tr><td>FileAttribute::Directory</td> <td>Directory</td></tr>
* <tr><td>FileAttribute::SymbolicLink</td> <td>Symbolic link</td></tr>
* <tr><td>FileAttribute::Socket</td> <td>Socket</td></tr>
* <tr><td>FileAttribute::FileType</td> <td>Mask to isolate file type flags</td></tr>
* <tr><td colspan="2"><b>File attributes</b>\n
* <em>These are Windows-exclusive, except ReadOnly and Hidden, which we emulate on UNIX and Linux platforms.</em></td></tr>
* <tr><td>FileAttribute::Archive</td> <td>File is archived</td></tr>
* <tr><td>FileAttribute::Compressed</td> <td>File is compressed</td></tr>
* <tr><td>FileAttribute::Encrypted</td> <td>File is encrypted</td></tr>
* <tr><td>FileAttribute::Hidden</td> <td>File is hidden</td></tr>
* <tr><td>FileAttribute::ReadOnly</td> <td>File is read-only</td></tr>
* <tr><td>FileAttribute::System</td> <td>File is a system file</td></tr>
* <tr><td>FileAttribute::Temporary</td> <td>File is a temporary file</td></tr>
* <tr><td>FileAttribute::FileAttributes</td> <td>Mask to isolate file attributes flags</td></tr>
* <tr><td colspan="2"><b>File permissions</b></td></tr>
* <tr><td>FileAttribute::Read</td> <td>Owner can read</td></tr>
* <tr><td>FileAttribute::Write</td> <td>Owner can write</td></tr>
* <tr><td>FileAttribute::Execute</td> <td>Owner can execute/search</td></tr>
* <tr><td>FileAttribute::ReadGroup</td> <td>Group can read</td></tr>
* <tr><td>FileAttribute::WriteGroup</td> <td>Group can write</td></tr>
* <tr><td>FileAttribute::ExecuteGroup</td> <td>Group can execute/search</td></tr>
* <tr><td>FileAttribute::ReadOthers</td> <td>Others can read</td></tr>
* <tr><td>FileAttribute::WriteOthers</td> <td>Others can write</td></tr>
* <tr><td>FileAttribute::ExecuteOthers</td> <td>Others can execute/search</td></tr>
* <tr><td>FileAttribute::FilePermissions</td> <td>Mask to isolate file permission flags</td></tr>
* </table>
*
* \ingroup file_utilities
*/
namespace FileAttribute
{
enum mask_type
{
/*
* File type.
*/
Block = 0x00000001, // Block special
Character = 0x00000002, // Character special
FIFO = 0x00000004, // FIFO special
Regular = 0x00000008, // Regular file
Directory = 0x00000010, // Directory
SymbolicLink = 0x00000020, // Symbolic link
Socket = 0x00000040, // Socket
FileType = 0x000000FF,
/*
* File attributes.
* These are Windows-exclusive, except ReadOnly and Hidden, which we
* emulate on UNIX and Linux.
*/
Archive = 0x00001000, // File is archived
Compressed = 0x00002000, // File is compressed
Encrypted = 0x00004000, // File is encrypted
Hidden = 0x00008000, // File is hidden
ReadOnly = 0x00010000, // File is read-only
System = 0x00020000, // File is a system file
Temporary = 0x00040000, // File is a temporary file
FileAttributes = 0x000FF000,
/*
* File permissions.
*/
Read = 0x00100000, // Owner can read
Write = 0x00200000, // Owner can write
Execute = 0x00400000, // Owner can execute/search
ReadGroup = 0x01000000, // Group can read
WriteGroup = 0x02000000, // Group can write
ExecuteGroup = 0x04000000, // Group can execute/search
ReadOthers = 0x10000000, // Others can read
WriteOthers = 0x20000000, // Others can write
ExecuteOthers = 0x40000000, // Others can execute/search
FilePermissions= 0xFFF00000
};
}
/*!
* \class pcl::FileAttributes
* \brief A combination of file type, attribute and access mode flags
* \ingroup file_utilities
*/
typedef Flags<FileAttribute::mask_type> FileAttributes;
// ----------------------------------------------------------------------------
/*!
* \struct FileTime
* \brief File date and time
*
* %FileTime is used to represent the creation, last access and last
* modification times of a file or directory. On most file systems, this object
* represents a time point in the Coordinated Universal Time (UTC) time scale.
* \ingroup file_utilities
*/
struct FileTime
{
uint16 year : 16; //!< Year
uint8 month : 4; //!< Month [1,12]
uint8 day : 5; //!< Day [1,31]
uint8 hour : 5; //!< Hour [0,23]
int : 2;
uint8 minute : 6; //!< Minute [0,59]
uint8 second : 6; //!< Second [0,59]
int : 4;
uint16 milliseconds : 10; //!< Milliseconds [0,999]
int : 6;
/*!
* Returns true iff this file time is equal to another object \a t.
*/
bool operator ==( const FileTime& t ) const
{
return second == t.second && minute == t.minute && hour == t.hour &&
day == t.day && month == t.month && year == t.year &&
milliseconds == t.milliseconds;
}
/*!
* Returns true iff this file time precedes another object \a t.
*/
bool operator <( const FileTime& t ) const
{
if ( year != t.year ) return year < t.year;
if ( month != t.month ) return month < t.month;
if ( day != t.day ) return day < t.day;
if ( hour != t.hour ) return hour < t.hour;
if ( minute != t.minute ) return minute < t.minute;
if ( second != t.second ) return second < t.second;
if ( milliseconds != t.milliseconds ) return milliseconds < t.milliseconds;
return false;
}
/*!
* Returns this file date and time as a Julian day number. The returned
* value represents a time point in the UTC time scale on most file systems.
*/
double ToJD() const;
/*!
* Returns the elapsed time in days since the standard UNIX epoch (1970
* January 1.0 UTC).
*/
double DaysSinceEpoch() const
{
return ToJD() - 2440587.5;
}
/*!
* Returns the elapsed time in seconds since the standard UNIX epoch (1970
* January 1.0 UTC).
*/
double SecondsSinceEpoch() const
{
return 86400*DaysSinceEpoch();
}
};
// ----------------------------------------------------------------------------
/*!
* \struct FindFileInfo
* \brief %File information structure used by File::Find
* \ingroup file_utilities
* \sa pcl::File::Find
*/
struct FindFileInfo
{
String name; //!< File or directory name, including the file name extension.
FileAttributes attributes; //!< Item attributes.
fsize_type size; //!< File size in bytes.
int numberOfLinks; //!< Number of existing hard links to this file.
int userId; //!< User id of the file owner.
int groupId; //!< Group id of the file owner.
FileTime created; //!< Creation time.
FileTime lastAccessed; //!< Time of last access.
FileTime lastModified; //!< Time of last change.
/*!
* Returns true iff this %FindFileInfo structure corresponds to a directory.
*/
bool IsDirectory() const
{
return attributes.IsFlagSet( FileAttribute::Directory );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::Archive attribute set.
*/
bool IsArchive() const
{
return attributes.IsFlagSet( FileAttribute::Archive );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::Compressed attribute set.
*/
bool IsCompressed() const
{
return attributes.IsFlagSet( FileAttribute::Compressed );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::Encrypted attribute set.
*/
bool IsEncrypted() const
{
return attributes.IsFlagSet( FileAttribute::Encrypted );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::Hidden attribute set.
*/
bool IsHidden() const
{
return attributes.IsFlagSet( FileAttribute::Hidden );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::ReadOnly attribute set.
*/
bool IsReadOnly() const
{
return attributes.IsFlagSet( FileAttribute::ReadOnly );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::System attribute set.
*/
bool IsSystem() const
{
return attributes.IsFlagSet( FileAttribute::System );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to a file with the
* FileAttribute::Temporary attribute set.
*/
bool IsTemporary() const
{
return attributes.IsFlagSet( FileAttribute::Temporary );
}
/*!
* Returns true iff this %FindFileInfo structure corresponds to an empty file.
*/
bool IsEmpty() const
{
return size == 0;
}
};
// ----------------------------------------------------------------------------
/*!
* \namespace pcl::ReadTextOption
* \brief File text reading options.
*
* <table border="1" cellpadding="4" cellspacing="0">
* <tr><td>RemoveEmptyLines</td> <td>Discard empty text lines (after trimming whitespace, when applicable).</td></tr>
* <tr><td>TrimTrailingSpaces</td> <td>Delete trailing whitespace characters from input text lines.</td></tr>
* <tr><td>TrimLeadingSpaces</td> <td>Delete leading whitespace characters from input text lines.</td></tr>
* <tr><td>TrimSpaces</td> <td>Delete both leading and trailing whitespace characters from input text lines.</td></tr>
* </table>
*
* \ingroup file_utilities
* \sa File::ReadLines(), File::ScanLines()
*/
namespace ReadTextOption
{
enum mask_type
{
RemoveEmptyLines = 0x0001,
TrimTrailingSpaces = 0x0002,
TrimLeadingSpaces = 0x0004,
TrimSpaces = TrimTrailingSpaces | TrimLeadingSpaces
};
}
/*!
* \class pcl::ReadTextOptions
* \brief A combination of file text reading mode flags
* \ingroup file_utilities
* \sa File::ReadLines(), File::ScanLines()
*/
typedef Flags<ReadTextOption::mask_type> ReadTextOptions;
// ----------------------------------------------------------------------------
/*!
* \struct UniqueFileChecks
* \brief A simple POD structure to hold file uniqueness and overwrite
* verification results.
* \ingroup file_utilities
* \sa File::EnsureNewUniqueFilePath()
*/
struct UniqueFileChecks
{
bool exists = false;
bool overwrite = false;
};
// ----------------------------------------------------------------------------
/*!
* \class File
* \brief A platform-independent interface to the local file system
*
* ### TODO: Write a detailed description for %File.
*
* \ingroup file_utilities
*/
class PCL_CLASS File
{
public:
/*!
* Represents a low-level opaque handle to a file.
*/
typedef void* handle;
/*!
* Represents a file seek mode.
*/
typedef SeekMode::value_type seek_mode;
/*!
* \class pcl::File::Error
* \brief File I/O exception
* \ingroup file_utilities
*/
class PCL_CLASS Error : public pcl::Error
{
public:
/*!
* Constructs a %File::Error object with the specified full file
* \a path and error \a message.
*/
Error( const String& filePath, const String& message )
: pcl::Error( message )
, m_filePath( filePath )
{
}
/*!
* Copy constructor.
*/
Error( const Error& ) = default;
/*!
*/
String ExceptionClass() const override
{
return "File I/O Error";
}
/*!
* Returns the full file path associated to this file error.
*/
virtual String FilePath() const
{
return m_filePath;
}
/*!
*/
virtual String ErrorMessage() const
{
return m_message;
}
/*!
*/
String Message() const override
{
String filePath = FilePath();
String message = m_message;
if ( !filePath.IsEmpty() )
{
message += ": ";
message += filePath;
}
return message;
}
private:
String m_filePath;
};
/*!
* \class pcl::File::Find
* \brief Directory search operation
*
* This class can be used as an iterator to find all files and
* subdirectories within a directory tree.
*
* In the following example, the ProcessFiles function calls a functor
* object, specified as the \a processFile function argument, for each file
* found recursively in the specified \a dirPath directory. The functor's
* unique argument is the absolute file path of an existing file.
*
* \code
* template <class F>
* void ProcessFiles( const String& dirPath, F processFile )
* {
* StringList directories;
* pcl::FindFileInfo info;
* for ( File::Find f( dirPath + '/' + '*' ); f.NextItem( info ); )
* if ( info.IsDirectory() )
* {
* if ( info.name != "." && info.name != ".." )
* directories << info.name;
* }
* else if ( !info.attributes.IsFlagSet( FileAttribute::SymbolicLink ) )
* {
* processFile( File::FullPath( dirPath + '/' + info.name ) );
* }
* for ( const String& dir : directories )
* ProcessFiles( dirPath + '/' + dir );
* }
* \endcode
*
* \ingroup file_utilities
* \sa FindFileInfo
*/
class PCL_CLASS Find
{
public:
/*!
* Constructs an inactive %File::Find object.
*/
Find() = default;
/*!
* Constructs a %File::Find object and starts a new directory search
* operation for the specified \a path.
*
* The specified \a path can include wildcards to define a pattern to
* search for a set of directory items.
*/
Find( const String& path )
{
Begin( path );
}
/*!
* Destroys a %File::Find object. If a directory search operation is
* currently active, it is finalized.
*/
~Find()
{
End();
}
/*!
* Copy constructor. This constructor is disabled because %File::Find
* instances are unique.
*/
Find( const Find& ) = delete;
/*!
* Copy assignment. This operator is disabled because %File::Find
* instances are unique.
*/
Find& operator =( const Find& ) = delete;
/*!
* Starts a new directory search operation for the specified \a path.
*
* The specified \a path can include wildcards to define a pattern to
* search for a set of directory items.
*/
void Begin( const String& path );
/*!
* Attempts to retrieve the next item in the current directory search
* operation.
*
* Returns true if a new item has been retrieved. In such case the
* \a info structure receives the data corresponding to the retrieved
* item. Returns false if there are no more items available, signaling
* the end of the current directory search operation, or if a search
* operation has not been initiated by a previous call to Begin(). In
* such case the \a info structure is not modified.
*/
bool NextItem( FindFileInfo& info );
/*!
* Finalizes the current directory search operation, if there is one
* active.
*/
void End();
/*!
* Returns the search path of the current directory search operation.
*/
String SearchPath() const
{
return m_searchPath;
}
private:
FindFileInfo m_info;
String m_searchPath;
#ifndef __PCL_WINDOWS
String m_searchDir;
String m_searchName;
#endif
void* m_handle = nullptr;
};
/*!
* \class pcl::File::Progress
* \brief Abstract base class of file progress objects
*
* The purpose of a file progress object is to provide feedback to the user
* during potentially long file tasks, such as copying, moving and deleting
* large files or file sets. The %File::Progress class provides a simple
* template with a text line, an increasing counter, and the possibility to
* abort a long operation.
*
* \ingroup file_utilities
* \sa File::CopyFile(), File::MoveFile()
*/
class PCL_CLASS Progress
{
public:
/*!
* Constructs a %File::Progress object.
*
* \param total Total progress count (for example, the total size
* in bytes of a file being copied, or the total
* number of files being deleted).
*
* \param initialText Initial progress text. The default value is an
* empty string.
*
* \param initialValue Initial progress value. The default value is
* zero.
*/
Progress( fsize_type total, const String& initialText = String(), fsize_type initialValue = 0 )
: m_total( Max( fsize_type( 0 ), total ) )
, m_current( Range( initialValue, fsize_type( 0 ), m_total ) )
, m_text( initialText )
{
}
/*!
* Destroys a %File::Progress object.
*/
virtual ~Progress()
{
}
/*!
* Returns the total progress count.
*/
fsize_type Total() const
{
return m_total;
}
/*!
* Returns the current progress count.
*/
fsize_type Value() const
{
return m_current;
}
/*!
* Returns the current progress text.
*/
const String& Text() const
{
return m_text;
}
/*!
* Sets the \a current progress count.
*
* This member function can abort the ongoing task. In such case, a
* ProcessAborted exception is thrown and the IsAborted() member function
* returns true.
*/
void SetValue( fsize_type current )
{
if ( current >= m_current )
{
m_current = current;
if ( !ValueChanged() )
{
m_abort = true;
throw ProcessAborted();
}
}
}
/*!
* Adds \a delta items to the current progress count.
*
* This member function can abort the ongoing task. In such case, a
* ProcessAborted exception is thrown and the IsAborted() member function
* returns true.
*/
void Add( fsize_type delta )
{
if ( delta >= 0 )
{
m_current += delta;
if ( !ValueChanged() )
{
m_abort = true;
throw ProcessAborted();
}
}
}
/*!
* Changes the current progress \a text.
*
* This member function can abort the ongoing task. In such case, a
* ProcessAborted exception is thrown and the IsAborted() member function
* returns true.
*/
void SetText( const String& text )
{
m_text = text;
if ( !TextChanged() )
{
m_abort = true;
throw ProcessAborted();
}
}
/*!
* Returns true iff this object aborted a running task.
*/
bool IsAborted() const
{
return m_abort;
}
protected:
fsize_type m_total;
fsize_type m_current;
String m_text;
bool m_abort = false;
/*!
* Function called when the current progress count has been changed.
* Returns true to continue the running task; false to abort.
*
* This is a pure virtual function that must be reimplemented by derived
* classes.
*/
virtual bool ValueChanged() = 0;
/*!
* Function called when the current progress text has been changed.
* Returns true to continue the running task; false to abort.
*
* This is a pure virtual function that must be reimplemented by derived
* classes.
*/
virtual bool TextChanged() = 0;
};
// -------------------------------------------------------------------------
/*!
* Constructs a %File object that does not represent an existing file.
*/
File()
{
Initialize();
}
/*!
* Constructs a %File object that opens a file at a given \a path with the
* specified \a mode.
*/
File( const String& path, FileModes mode )
{
PCL_PRECONDITION( !path.IsEmpty() )
Initialize();
Open( path, mode );
}
/*!
* Move constructor.
*/
File( File&& x )
: m_fileHandle( x.m_fileHandle )
, m_filePath( std::move( x.m_filePath ) )
, m_fileMode( x.m_fileMode )
{
x.m_fileHandle = s_invalidHandle;
x.m_fileMode = FileMode::Zero;
}
/*!
* Move assignment operator. Returns a reference to this object.
*/
File& operator =( File&& x )
{
if ( &x != this )
{
if ( IsOpen() )
Close();
m_fileHandle = x.m_fileHandle;
m_filePath = std::move( x.m_filePath );
m_fileMode = x.m_fileMode;
x.m_fileHandle = s_invalidHandle;
x.m_fileMode = FileMode::Zero;
}
return *this;
}
/*!
* Destroys a %File object. If this instance represents an open file, it is
* closed upon destruction.
*/
virtual ~File()
{
if ( IsOpen() )
Close();
}
/*!
* Copy constructor. This constructor is disabled because files are unique
* objects.
*/
File( const File& ) = delete;
/*!
* Copy assignment. This operator is disabled because files are unique
* objects.
*/
File& operator =( const File& ) = delete;
/*!
* Returns true iff this %File object represents an open file.
*/
bool IsOpen() const
{
return IsValidHandle( m_fileHandle );
}
/*!
* Returns the path of the file represented by this %File object.
* Returned file paths are always absolute, full file paths.
*/
const String& FilePath() const
{
return m_filePath;
}
/*!
* Returns the path of the file represented by this %File object.
*
* \deprecated This member function has been deprecated. Use FilePath() in
* newly produced code.
*/
const String& FileName() const
{
return FilePath();
}
/*!
* Returns the file mode for this %File object.
*/
FileModes Mode() const
{
return m_fileMode;
}
/*!
* Returns true iff this file allows read access.
*/
virtual bool CanRead() const
{
return m_fileMode.IsFlagSet( FileMode::Read );
}
/*!
* Returns true iff this file allows write access.
*/
virtual bool CanWrite() const
{
return m_fileMode.IsFlagSet( FileMode::Write );
}
/*!
* Returns the current file position, relative to the beginning of the file
* represented by this %File object.
*/
virtual fpos_type Position() const;
/*!
* Sets the file position relative to the file beginning.
*/
virtual void SetPosition( fpos_type pos );
/*!
* Moves the file pointer. Returns the resulting pointer position from the
* file beginning.
*
* \param dist Distance to move in bytes.
* \param mode Seek mode. See the SeekMode namespace for valid modes.
*/
fpos_type Seek( fpos_type dist, seek_mode mode = SeekMode::FromCurrent );
/*!
* Moves the file pointer after the end of the file.
* Returns the size of this file, that is, the absolute position of the last
* byte plus one.
*
* This is a convenience member function, equivalent to
* Seek( 0, SeekMode::FromEnd )
*/
fpos_type SeekEnd()
{
return Seek( 0, SeekMode::FromEnd );
}
/*!
* Moves the file pointer to the beginning of this file.
*
* This is a convenience member function, equivalent to SetPosition( 0 )
*/
void Rewind()
{
SetPosition( 0 );
}
/*!
* Returns true iff the file pointer has been moved beyond the end of the
* file.
*/
bool IsEOF() const
{
return Position() >= Size();
}
/*!
* Returns the length in bytes of this file.
*/
virtual fsize_type Size() const;
/*!
* Truncates or extends this file to the specified \a length.
*/
virtual void Resize( fsize_type length );
/*!
* Reads a contiguous block of \a len bytes into the specified \a buffer.
*/
virtual void Read( void* buffer, fsize_type len );
/*!
* Reads an object \a x of type T.
*/
template <typename T>
void Read( T& x )
{
Read( (void*)&x, sizeof( T ) );
}
/*!
* Reads a set of \a n consecutive objects of type T into the array pointed
* to by \a a.
*
* This is a convenience member function, equivalent to
* Read( (void*)a, n*sizeof( T ) )
*/
template <typename T>
void ReadArray( T* a, size_type n )
{
Read( (void*)a, n*sizeof( T ) );
}
/*!
* Reads a numeric variable as a 32-bit signed integer.
*/
template <typename T>
void ReadI32( T& x )
{
int32 i; Read( i ); x = T( i );
}
/*!
* Reads a numeric variable as a 32-bit unsigned integer.
*/
template <typename T>
void ReadUI32( T& x )
{
uint32 i; Read( i ); x = T( i );
}
/*!
* Reads a numeric variable as a 64-bit signed integer.
*/
template <typename T>
void ReadI64( T& x )
{
int64 i; Read( i ); x = T( i );
}
/*!
* Reads a numeric variable as a 64-bit unsigned integer.
*/
template <typename T>
void ReadUI64( T& x )
{
uint64 i; Read( i ); x = T( i );
}
/*!
* Writes a contiguous block of \a len bytes from the specified \a buffer.
*/
virtual void Write( const void* buffer, fsize_type len );
/*!
* Writes an object \a x of type T.
*/
template <typename T>
void Write( const T& x )
{
Write( (const void*)&x, sizeof( T ) );
}
/*!
* Writes a set of \a n consecutive objects of type T from the array pointed
* to by \a a.
*
* This is a convenience member function, equivalent to
* Write( (const void*)a, n*sizeof( T ) )
*/
template <typename T>
void WriteArray( const T* a, size_type n )
{
Write( (const void*)a, n*sizeof( T ) );
}
/*!
* Writes a numeric variable as a 32-bit signed integer.
*/
template <typename T>
void WriteI32( const T& x )
{
Write( int32( x ) );
}
/*!
* Writes a numeric variable as a 32-bit unsigned integer.
*/
template <typename T>
void WriteUI32( const T& x )
{
Write( uint32( x ) );
}
/*!
* Writes a numeric variable as a 64-bit signed integer.
*/
template <typename T>
void WriteI64( const T& x )
{
Write( int64( x ) );
}
/*!
* Writes a numeric variable as a 64-bit unsigned integer.
*/
template <typename T>
void WriteUI64( const T& x )
{
Write( uint64( x ) );
}
/*!
* Reads a boolean variable.
*
* This function reads a 32-bit integer and assigns true to the variable
* \a b iff the read number is nonzero.
*/
void Read( bool& b )
{
unsigned i; ReadUI32( i ); b = i != 0;
}
/*!
* Writes a boolean variable.
*
* This function writes a 32-bit integer with a value of 1 (one) if the
* variable \a b is true, zero otherwise.
*/
void Write( const bool& b )
{
WriteUI32( b ? 1 : 0 );
}
/*!
* Reads a dynamic 8-bit string stored as binary data. The data should have
* been generated by a previous call to Write( const IsoString& ) on the
* file being read.
*/
void Read( IsoString& s );
/*!
* Reads a dynamic UTF-16 string stored as binary data. The data should have
* been generated by a previous call to Write( const IsoString& ) on the
* file being read.
*/
void Read( String& s );
/*!
* Writes a sequence of 8-bit characters, defined by the range [i,j), as
* binary data.
*/
void Write( const char* i, const char* j );
/*!
* Writes a null-terminated 8-bit string as binary data.
*/
void Write( const char* s )
{
Write( s, s + IsoCharTraits::Length( s ) );
}
/*!
* Writes a dynamic 8-bit string as binary data.
*/
void Write( const IsoString& s )
{
Write( s.Begin(), s.End() );
}
/*!
* Writes a sequence of UTF-16 characters, defined by the range [i,j), as
* binary data.
*/
void Write( const char16_type* i, const char16_type* j );
/*!
* Writes a null-terminated string of UTF-16 characters as binary data.
*/
void Write( const char16_type* s )
{
Write( s, s + CharTraits::Length( s ) );
}
/*!
* Writes a dynamic UTF-16 string as binary data.
*/
void Write( const String& s )
{
Write( s.Begin(), s.End() );
}
#ifndef __PCL_NO_FLAGS_FILE_IO
/*!
* Reads a set of flags \a f.
*/
template <typename E>
static void Read( Flags<E>& f )
{
Read( f.m_flags );
}
/*!
* Reads a set of flags \a f as an unsigned 32-bit integer.
*/
template <typename E>
static void ReadUI32( Flags<E>& f )
{
ReadUI32( f.m_flags );
}
/*!
* Writes a set of flags \a f.
*/
template <typename E>
static void Write( Flags<E> f )
{
Write( f.m_flags );
}
/*!
* Writes a set of flags \a f as an unsigned 32-bit integer.
*/
template <typename E>
static void WriteUI32( Flags<E> f )
{
WriteUI32( f.m_flags );
}
#endif
/*!
* Writes a sequence of 8-bit characters, defined by the range [i,j), as
* plain text.
*/
void OutText( const char* i, const char* j )
{
if ( i < j )
Write( (const void*)i, fsize_type( j - i ) );
}
/*!
* Writes a null-terminated 8-bit string as plain text.
*/
void OutText( const char* s )
{
OutText( s, s + IsoCharTraits::Length( s ) );
}
/*!
* Writes a dynamic 8-bit string as plain text.
*/
void OutText( const IsoString& s )
{
OutText( s.Begin(), s.End() );
}
/*!
* Writes a sequence of UTF-16 characters, defined by the range [i,j), as
* plain text.
*/
void OutText( const char16_type* i, const char16_type* j )
{
if ( i < j )
Write( (const void*)i, fsize_type( j - i ) << 1 );
}
/*!
* Writes a null-terminated UTF-16 string as plain text.
*/
void OutText( const char16_type* s )
{
OutText( s, s + CharTraits::Length( s ) );
}
/*!
* Writes a dynamic UTF16 string as plain text.
*/
void OutText( const String& s )
{
OutText( s.Begin(), s.End() );
}
/*!
* Writes a sequence of 8-bit characters, defined by the range [i,j), as
* plain text. Then writes a newline character.
*/
void OutTextLn( const char* i, const char* j )
{
OutText( i, j ); Write( '\n' );
}
/*!
* Writes a null-terminated 8-bit string as plain text and appends a newline
* character.
*/
void OutTextLn( const char* s )
{
OutText( s ); Write( '\n' );
}
/*!
* Writes an 8-bit newline character ('\n').
*
* \warning Do not use this member function if you are generating plain text
* encoded as UTF-16, for example in a sequence of calls to
* OutTextLn( const String& s ). In such case you can call:\n
* \n
* \code OutTextLn( String() ); \endcode \n
* \n
* to generate a newline in UTF-16 format.
*/
void OutTextLn()
{
Write( '\n' );
}
/*!
* Writes a dynamic 8-bit string as plain text and appends a newline
* character.
*/
void OutTextLn( const IsoString& s )
{
OutText( s ); Write( '\n' );
}
/*!
* Writes a sequence of UTF-16 characters, defined by the range [i,j), as
* plain text. Then writes a newline character.
*/
void OutTextLn( const char16_type* i, const char16_type* j )
{
OutText( i, j ); Write( char16_type( '\n' ) );
}
/*!
* Writes a null-terminated UTF-16 string as plain text and appends a
* newline character.
*/
void OutTextLn( const char16_type* s )
{
OutText( s ); Write( char16_type( '\n' ) );
}
/*!
* Writes a dynamic UTF16 string as plain text and appends a newline
* character.
*/
void OutTextLn( const String& s )
{
OutText( s ); Write( char16_type( '\n' ) );
}
/*!
* Commits any pending write operations.
*/
void Flush();
/*!
* Opens or creates a file.
*
* \param path The path to the file to be opened or created.
*
* \param mode Desired file access, share (Windows only) and
* opening/creation mode. By default, an existing file will
* be opened for (exclusive on Windows) read-only access.
*/
virtual void Open( const String& path, FileModes mode = FileMode::Read|FileMode::Open );
/*!
* Opens an existing file at the specified \a path. On Windows, the file is
* opened for shared read-only access (on UNIX and Linux, file access is
* handled automatically, so there is no need to define 'sharing modes').
*/
virtual void OpenForReading( const String& path )
{
Open( path, FileMode::Read|FileMode::Open|FileMode::ShareRead );
}
/*!
* Returns an open existing file at the specified \a path. On Windows, the
* file is opened for shared read-only access (on UNIX and Linux, file
* access is handled automatically, so there is no need to define 'sharing
* modes').
*/
static File OpenFileForReading( const String& path )
{
File f;
f.OpenForReading( path );
return f;
}
/*!
* Opens an existing file at \a path for exclusive read/write access.
*/
virtual void OpenForReadWrite( const String& path )
{
Open( path, FileMode::Read|FileMode::Write|FileMode::Open );
}
/*!
* Returns an open existing file at the specified \a path, ready for
* exclusive read/write access.
*/
static File OpenFileForReadWrite( const String& path )
{
File f;
f.OpenForReadWrite( path );
return f;
}
/*!
* Creates a file at the specified \a path for exclusive read/write access.
* If a file already exists at the same \a path, its contents will be
* truncated to zero length.
*/
virtual void Create( const String& path )
{
Open( path, FileMode::Read|FileMode::Write|FileMode::Create );
}
/*!
* Returns a newly created file at the specified \a path, ready for
* exclusive read/write access. If a file already exists at the same
* \a path, its contents will be truncated to zero length.
*/
static File CreateFile( const String& path )
{
File f;
f.Create( path );
return f;
}
/*!
* Creates a file at the specified \a path for exclusive write-only access.
* If a file already exists at the same \a path, its contents will be
* truncated to zero length.
*/
virtual void CreateForWriting( const String& path )
{
Open( path, FileMode::Write|FileMode::Create );
}
/*!
* Returns a newly created file at the specified \a path, ready for
* exclusive write-only access. If a file already exists at the same
* \a path, its contents will be truncated to zero length.
*/
static File CreateFileForWriting( const String& path )
{
File f;
f.CreateForWriting( path );
return f;
}
/*!
* Opens a file at the specified \a path if it exists, or creates it
* otherwise. The file will be opened in exclusive read/write mode.
*/
void OpenOrCreate( const String& path )
{
Open( path, FileMode::Read|FileMode::Write|FileMode::Open|FileMode::Create );
}
/*!
* Returns an open file at the specified \a path if it already exists, or a
* newly created file otherwise, ready for exclusive read/write access.
*/
static File OpenOrCreateFile( const String& path )
{
File f;
f.OpenOrCreate( path );
return f;
}
/*!
* Closes an open file. If this file has not been opened, calling this
* member function has no effect.
*/
virtual void Close();
/*!
* Removes an existing file at the specified \a filePath.
*/
static void Remove( const String& filePath );
/*!
* Creates a new directory at the specified \a dirPath.
*
* If \a createIntermediateDirectories is true (the default value) and
* \a dirPath specifies one or more parent directories that don't exist,
* they are created automatically.
*/
static void CreateDirectory( const String& dirPath, bool createIntermediateDirectories = true );
/*!
* Removes an existing \e empty directory at the specified \a dirPath.
*
* The specified directory must be empty, or this function will fail.
*/
static void RemoveDirectory( const String& dirPath );
/*!
* Moves and/or renames a file.
*
* \param filePath Current path of the file to move/rename
*
* \param newFilePath New path. If the directory in \a newFilePath is the
* same as in \a filePath, or if no directory is specified, the
* file is just renamed. If a different directory is specified,
* the file is also moved.
*
* \warning This function can only move or rename a file to stay in the same
* physical device. To move a file across devices, use the File::MoveFile()
* static member function.
*/
static void Move( const String& filePath, const String& newFilePath );
/*!
* Returns true iff a file at the specified \a filePath exists.
*/
static bool Exists( const String& filePath );
/*!
* Returns true iff a directory at the specified \a dirPath exists.
*/
static bool DirectoryExists( const String& dirPath );
/*!
* Ensures existence of a file on the local filesystem, guaranteeing that a
* newly created file cannot replace or overwrite an already existing file,
* or clash with an existing directory.
*
* \param[in,out] filePath Path to the file that must exist with
* guaranteed uniqueness. The value of the variable referenced
* by this parameter can be modified on output; see the
* \a canOverwrite parameter and the description below for
* further details.
*
* \param canOverwrite If this parameter is false and the specified
* \a filePath corresponds to an already existing file, the
* string referenced by \a filePath will be replaced on output
* with a new path on the same directory where the file name has
* been modified to guarantee that no file existed with the same
* name upon calling this function. If this parameter is true
* the \a filePath string won't be modified in any way.
*
* After calling this function, a file at the path specified by the output
* value of the \a filePath variable is guaranteed to exist, either because
* such file already existed when the function was called and the
* \a canOverwrite parameter was true, or because a new empty file has been
* created otherwise. Already existing files are never touched or modified
* in any way by this function (beyond the fact that they are accessed to
* verify their existence).
*
* Returns a UniqueFileChecks structure where the \a exists member indicates
* whether the specified \a filePath corresponds to an already existing file
* upon calling this function, and the \a overwrite member is true iff an
* existing file can be overwritten because the specified \a canOverwrite
* parameter is true.
*
* When the \a filePath string is altered to provide a unique file name, the
* file path is made unique by appending the literal representation of an
* unsigned integer, preceded by an underscore character, to the file name
* component. For example, if this function is called as follows when the
* specified file already exists:
*
* \code
* String filePath = "/path/to/foo.bar"; // this file exists
* EnsureNewUniqueFile( filePath );
* \endcode
*
* then the \c filePath variable could have the value "/path/to/foo_1.bar",
* and a new, empty file would have been created at that path. Successive
* calls would set \c filePath equal to "/path/to/foo_2.bar",
* "/path/to/foo_3.bar", and so on, creating the corresponding new files.
*
* \note This static member function is thread-safe. It will provide
* coherent results when invoked from multiple threads running concurrently.
*/
static UniqueFileChecks EnsureNewUniqueFile( String& filePath, bool canOverwrite = false );
/*!
* Ensures existence of a directory on the local filesystem, guaranteeing
* that a new, empty directory will be created in case a file or directory
* at the specified path already existed when the function was called.
*
* \param[in,out] dirPath Path to the directory that must exist with
* guaranteed uniqueness. The value of the variable referenced
* by this parameter can be modified on output; see the
* description below for further details.
*
* After calling this function, a directory at the path specified by the
* output value of the \a dirPath variable is guaranteed to exist, either
* because such directory already existed when the function was called, or
* because a new empty directory has been created otherwise. Already
* existing directories or files are never touched or modified in any way by
* this function (beyond the fact that they are accessed to verify their
* existence).
*
* Returns a UniqueFileChecks structure where the \a exists member indicates
* whether the specified \a dirPath corresponds to an already existing
* directory upon calling this function, and the \a overwrite member is
* always false, reflecting the fact that a directory cannot be overwritten.
*
* If the specified directory already exists, the string referenced by
* \a dirPath will be altered to provide a unique directory name on the same
* parent directory. In such case the path is made unique by appending the
* literal representation of an unsigned integer, preceded by an underscore
* character, to the file name component. For example, if this function is
* called as follows when the specified directory already exists:
*
* \code
* String dirPath = "/path/to/foobar"; // this directory exists
* EnsureNewUniqueDirectory( dirPath );
* \endcode
*
* then the \c dirPath variable could have the value "/path/to/foobar_1" and
* a new, empty directory would have been created at that path. Successive
* calls would set \c dirPath equal to "/path/to/foobar_2",
* "/path/to/foobar_3", and so on, creating the corresponding new
* directories.
*
* The string referenced by the specified \a dirPath variable can optionally
* end with a directory separator character, which will be preserved in case
* the string is modified.
*
* \note This static member function is thread-safe. It will provide
* coherent results when invoked from multiple threads running concurrently.
*/
static UniqueFileChecks EnsureNewUniqueDirectory( String& dirPath );
/*!
* Returns true iff the file at \a filePath exists and the current user has
* read-only access to it.
*/
static bool IsReadOnly( const String& filePath );
/*!
* Enables or disables read-only access to a file at the specified
* \a filePath.
*/
static void SetReadOnly( const String& filePath, bool rdOnly = true );
/*!
* Disables or enables read-only access to a file at the specified
* \a filePath.
*
* This is a convenience member function, equivalent to
* SetReadOnly( filePath, false )
*/
static void SetReadWrite( const String& filePath )
{
SetReadOnly( filePath, false );
}
/*!
* Reads the contents of a file at the specified \a filePath and returns
* them as a ByteArray object.
*/
static ByteArray ReadFile( const String& filePath );
/*!
* Creates a file with the specified contents.
*
* \param filePath Path to the file that will be created.
*
* \param contents Reference to a ByteArray object providing the contents
* that will be written to the newly created file.
*
* Typically this function is used along with File::ReadFile() to implement
* a file copying routine; for example:
*
* \code
* void CopyFile( const String& targetFilePath, const String& sourceFilePath )
* {
* File::WriteFile( targetFilePath, File::ReadFile( sourceFilePath ) );
* }
* \endcode
*
* \warning If a file already exists at the specified path, its previous
* contents will be lost after calling this function.
*/
static void WriteFile( const String& filePath, const ByteArray& contents );
/*!
* Creates a file with a subset of a ByteArray container.
*
* \param filePath Path to the file that will be created.
*
* \param contents Reference to a ByteArray object providing the contents
* that will be written to the newly created file.
*
* \param start Zero-based index of the first byte to be written.
*
* \param size Number of bytes that will be written.
*
* \warning If a file already exists at the specified path, its previous
* contents will be lost after calling this function.
*/
static void WriteFile( const String& filePath, const ByteArray& contents, size_type start, size_type size );
/*!
* Creates a file with the specified contents.
*
* \param filePath Path to the file that will be created.
*
* \param data Pointer to the first byte to be written to the newly
* created file.
*
* \param size Number of contiguous bytes, starting from \a data, to
* be written.
*
* \warning If a file already exists at the specified path, its previous
* contents will be lost after calling this function.
*/
static void WriteFile( const String& filePath, const void* data, size_type size );
/*!
* Reads the contents of a file at the specified \a filePath and returns
* them as plain text stored in a dynamic 8-bit string.
*
* This function is useful to load document files encoded in UTF-8,
* ISO/IEC-8859-1 (or Latin-1), and other 8-bit encodings.
*/
static IsoString ReadTextFile( const String& filePath );
/*!
* Creates a file with the specified plain text content.
*
* \param filePath Path to the file that will be created.
*
* \param text Reference to an IsoString object providing the plain
* text that will be written to the newly created file.
*
* This function is useful to generate document files encoded in UTF-8,
* ISO/IEC-8859-1 (or Latin-1), and other 8-bit encodings.
*
* \warning If a file already exists at the specified path, its previous
* contents will be lost after calling this function.
*/
static void WriteTextFile( const String& filePath, const IsoString& text );
/*!
* Changes the access permissions of a file or directory.
*
* \param targetPath Path to the existing file or directory whose
* permissions will be modified.
*
* \param permissions An ORed combination of file permission flags. See
* the FilePermission namespace for contants.
*
* On UNIX and Linux platforms (FreeBSD, GNU Linux, Mac OS X), the read,
* write and execution permissions can be specified separately for the owner
* user, for the owner group, and for the rest of users. On Windows, only
* generic read and write permissions can be set, and there are no execution
* permissions.
*/
static void SetPermissions( const String& targetPath, FileAttributes permissions );
/*!
* Copies access and modification times and access permissions from one
* file or directory item to another.
*
* \param targetPath Path to the target item whose times and permissions
* will be changed.
*
* \param sourcePath Path to the source item whose times and permissions
* will be copied to the target item.
*/
static void CopyTimesAndPermissions( const String& targetPath, const String& sourcePath );
#ifndef __PCL_WINDOWS
/*!
* Copies a symbolic link.
*
* \param targetLinkPath Path to the target file. A new symbolic link will
* be created at this path, which will point to the
* same link target as the source link.
*
* \param sourceLinkPath Path to the source link, whose target will be
* copied to the target link.
*
* Note that this function creates a duplicate of the symbolic link itself,
* \e not of its pointed file.
*
* \note This static member function is only defined on UNIX and Linux
* platforms. It does not make sense on Windows, where POSIX symbolic links
* don't exist.
*/
static void CopyLink( const String& targetLinkPath, const String& sourceLinkPath );
#endif // !__PCL_WINDOWS
/*!
* Copies a single file.
*
* \param targetFilePath Path to the target file, which must \e not exist.
* If the specified file exists, an Error exception
* will be thrown.
*
* \param sourceFilePath Path to the source file. This file must exist and
* must be different from the specified target file.
*
* \param progress Pointer to an instance of (a derived class of)
* File::Progress. If a non-null pointer is
* specified, the object will be used to provide
* progress information and the possibility of
* aborting the file copy operation. The default
* value is \c nullptr.
*
* The file copy operation is implemented as an iterative block copying
* routine. This means that huge files can be copied with minimal
* consumption of memory resources and no specific file size limit.
*
* Along with the file contents, file access and modification times, as well
* as file access permissions, will also be copied by this function.
*
* This function does not follow symbolic links. It does not copy the file
* pointed to by a symbolic link, but the link itself. This is only relevant
* to platforms that support symbolic links (i.e., all of them but Windows).
*
* If a \a progress object is specified, it receives successive calls to
* File::Progress::Add() with increments in bytes. If the progress object
* aborts the file copy operation, this member function throws a
* ProcessAborted exception.
*/
static void CopyFile( const String& targetFilePath, const String& sourceFilePath, File::Progress* progress = nullptr );
/*!
* Moves a single file.
*
* \param targetFilePath Path to the target file, which must \e not exist.
* If the specified file exists, an Error exception
* will be thrown.
*
* \param sourceFilePath Path to the source file. This file must exist and
* must be different from the specified target file.
*
* \param progress Pointer to an instance of (a derived class of)
* File::Progress. If a non-null pointer is
* specified, the object will be used to provide
* progress information and the possibility of
* aborting the file copy operation. The default
* value is \c nullptr.
*
* For file move operations within the same physical device, this function
* implements a simple rename operation. In these cases, the \a progress
* object (if specified) receives a single call to File::Progress::Add()
* with the total file size in bytes.
*
* When a file is moved to a different device, this member function first
* copies the source file to the target location using a routine equivalent
* to Copy(). When the entire file contents have been transferred, the
* source file is removed.
*
* Along with the file contents, file access and modification times, as well
* as file access permissions, will be preserved by this function.
*
* This function does not follow symbolic links. It does not move the file
* pointed to by a symbolic link, but the link itself. This is only relevant
* to platforms that support symbolic links (i.e., all of them but Windows).
*
* If a \a progress object is specified and it aborts the file move
* operation, this member function throws a ProcessAborted exception. In
* such case the source file is guaranteed to remain intact.
*/
static void MoveFile( const String& targetFilePath, const String& sourceFilePath, File::Progress* progress = nullptr );
/*!
* Returns true iff two files or directories are mounted on the same physical
* device.
*
* This is relevant to some critical file operations. For example, moving a
* file on the same device is a simple and fast rename operation. However,
* moving a file across devices involves copying the entire file contents.
*
* This function does not follow symbolic links. It does not consider
* mounted devices for files pointed to by symbolic links, but for the links
* themselves. This is only relevant to platforms that support symbolic
* links (all of them but Windows).
*/
static bool SameDevice( const String& path1, const String& path2 );
/*!
* Returns true iff two file path specifications refer to the same file on
* the system.
*
* On UNIX and Linux platforms, this function compares the device and inode
* numbers reported by the st_dev and st_ino members of the stat structure,
* respectively. This pair of numbers uniquely identifies every file on the
* system, irrespective of file names.
*
* On Windows platforms, this function verifies the devices that support
* both files and, if they are the same, performs a case-insensitive
* comparison of the canonical absolute versions of the specified paths.
*
* This function does not follow symbolic links. It does not consider
* mounted devices for files pointed to by symbolic links, but for the links
* themselves. This is only relevant to platforms that support symbolic
* links (all of them but Windows).
*/
static bool SameFile( const String& path1, const String& path2 );
/*!
* Reads all existing text lines from a file as 8-bit strings (e.g.,
* ISO 8859-1 or UTF-8 formats) and returns them as a string list.
*
* \param filePath Path to the source file from which text lines will
* be read.
*
* \param options Optional set of flags (ORed combination) that can be
* specified to control the way text lines are
* extracted and stored. Available flags are defined in
* the ReadTextOption namespace.
*
* Returns a string list (IsoStringList) with all existing lines in the
* specified file. If the file is empty, an empty string list is returned.
*
* This routine automatically detects and processes line ending sequences
* characteristic of all supported platforms: UNIX (LF = 0x0A), Windows
* (CR+LF = 0x0D+0x0A) and legacy Mac (CR = 0x0D).
*/
static IsoStringList ReadLines( const String& filePath,
ReadTextOptions options = ReadTextOptions() );
/*!
* Iterates a function through all existing text lines in a file.
*
* \param filePath Path to the source file from which text lines will
* be read. This file is assumed to store text as a
* sequence of 8-bit characters, e.g. ASCII, ISO 8859-1
* or UTF-8.
*
* \param callback Callback function. This function will be invoked
* once for each text line. The function will receive
* two arguments: a char* with the starting address of
* an 8-bit null terminated string, and a void* which
* is the specified \a data argument. The function will
* return true if the process can continue for the next
* text line; false to stop the iteration.
*
* \param data A void* that will be passed to the callback function
* as its second argument on each call. The default
* value is \c nullptr.
*
* \param options Optional set of flags (ORed combination) that can be
* specified to control the way text lines are explored
* and passed to the callback function. Available flags
* are defined in the ReadTextOption namespace.
*
* Returns the number of text lines that have been scanned, i.e. the number
* of times the callback function has been invoked and has returned true.
*
* This routine avoids all the work associated with creating and storing new
* IsoString objects. When IsoString instances are not necessary to acquire
* the data being read, this routine can be much faster than ReadLines(),
* especially for vey large files.
*
* This routine automatically detects and processes line ending sequences
* characteristic of all supported platforms: UNIX (LF = 0x0A), Windows
* (CR+LF = 0x0D+0x0A) and legacy Mac (CR = 0x0D).
*/
static size_type ScanLines( const String& filePath,
bool (*callback)( char*, void* ), void* data = nullptr,
ReadTextOptions options = ReadTextOptions() );
/*!
* Returns the full, absolute local path to the specified \a path.
*/
static String FullPath( const String& path );
/*!
* Returns a valid URI with the "file" scheme corresponding to the specified
* local \a path.
*
* The returned URI is valid as specified by RFC 1738 and RFC 8089. The
* following characters will always be percent-encoded when present in the
* specified \a path:
*
* - Non-printable US-ASCII characters in the ranges [00-1F] and [7F-FF].
*
* - Unsafe characters: ' ', '<', '>', '#', '"', '%', '{', '}', '|', '\\',
* '^', '~', '[', ']', '`'
*
* - Reserved characters: ';', '?', ':', '@', '=', '&'.
*
* The returned URI will include the specified path transformed to a full
* absolute local path with UNIX directory separators, encoded in UTF-8,
* percent-encoded as necessary, and prefixed with the "file://" scheme.
*
* On Windows, a drive letter will always be present, prefixed with a root
* directory specifier, and the colon separator will be used; for example:
*
* file:///c:/path/to/local%20file.txt
*
* \b References:
*
* https://tools.ietf.org/html/rfc1738 \n
* https://tools.ietf.org/html/rfc8089 \n
*/
static IsoString FileURI( const String& path );
/*!
* Returns the system temporary storage directory.
*
* On FreeBSD, Linux and macOS, this function returns the value of the
* TMPDIR environment variable if it is defined, nonempty, and is a valid
* path to an existing directory. Otherwise this function returns "/tmp".
*
* On Windows, this function returns the directory designated for storage of
* temporary files. Normally this is the value of the TMP or TEMP
* environment variable. If no valid directory can be retrieved this way
* (which is extremely weird), this function attempts to return the user's
* profile directory, as reported by the USERPROFILE variable. If that also
* fails, "C:/tmp" is returned if it exists, or the current working
* directory as a last resort.
*/
static String SystemTempDirectory();
/*!
* Returns the system cache storage directory.
*
* On FreeBSD, Linux and Windows, this function is equivalent to
* SystemTempDirectory().
*
* On macOS, this function returns the user's local cache folder, namely
* "~/Library/Caches" if it exists (it must), or SystemTempDirectory()
* otherwise.
*/
static String SystemCacheDirectory();
/*!
* Returns the home directory of the current user.
*
* On FreeBSD, Linux and macOS, this function returns the value of the HOME
* environment variable if it is defined, nonempty, and is a valid path to
* an existing directory. In the extremely weird case this does not happen,
* the system root directory '/' is returned as a last resort.
*
* On Windows, this function returns the root directory of the current
* user's profile. This is normally the value of the USERPROFILE environment
* variable. In case this fails, the HOMEDRIVE, HOMEPATH and HOME variables
* are checked for validity. If everything fails, the SYSTEMDRIVE variable
* is checked and ultimately "C:/" is returned.
*/
static String HomeDirectory();
/*!
* Converts a path from Windows to UNIX syntax. Replaces all occurrences of
* the '\\' Windows separator with the '/' UNIX separator.
*/
static String WindowsPathToUnix( const String& path );
/*!
* Converts a path from UNIX to Windows. Replaces all occurrences of
* the '/' UNIX separator with the '\\' Windows separator.
*/
static String UnixPathToWindows( const String& path );
/*!
* Returns a nonexistent, randomly generated file name.
*
* \param directory Name of an existing directory where the generated file
* name is guaranteed to be unique. If empty or not
* specified, the current directory of the calling process
* will be used.
*
* \param n Number of random characters in the generated file name.
* Must be at least five characters. The default value is
* twelve characters.
*
* \param prefix An optional prefix that will be prepended to the
* generated file name.
*
* \param postfix An optional postfix that will be appended to the
* generated file name.
*
* This function returns the full absolute path of a nonexistent file name
* generated by concatenation of \a n random characters. For compatibility
* with case-insensitive file systems (FAT, NTFS), only uppercase characters
* and decimal digits are used in the generated file name.
*
* The returned file name is guaranteed to be unique on the specified
* directory (or on the current directory of the calling process if no
* directory is specified) just after this function returns. Note that since
* a high-quality random number generator is used to select file name
* characters, there is no practical chance for a race condition by calling
* this function from several threads concurrently.
*/
static String UniqueFileName( const String& directory = String(), int n = 12,
const String& prefix = String(), const String& postfix = String() );
/*!
* Retrieves the storage space available on the device that supports a
* specified directory.
*
* \param dirPath A path specification to an existing directory on the
* local filesystem. On Windows, UNC paths are fully
* supported. Symbolic links are supported on all
* platforms. If a symbolic link is specified, the
* returned values refer to the target device.
*
* \param[out] totalBytes If non-null, the address of a variable that
* receives the total capacity in bytes of the device that
* supports the specified directory.
*
* \param[out] freeBytes If non-null, the address of a variable that
* receives the total number of free bytes on the device
* that supports the specified directory.
*
* Returns the total number of bytes available on the device that supports
* the specified directory. The returned values take into account any disk
* quotas that might apply to the user associated with the calling process.
*/
static uint64 GetAvailableSpace( const String& dirPath, uint64* totalBytes = nullptr, uint64* freeBytes = nullptr );
/*!
* Finds a Windows drive specification in the specified \a path.
*
* Returns the character index position of the drive found, or
* String::notFound.
*
* This function only makes sense on Windows. On UNIX and Linux operating
* systems, this function always returns String::notFound.
*/
static size_type FindDrive( const String& path );
/*!
* Finds a file name in the specified \a path.
*
* Returns the character index position of the name found, or
* String::notFound.
*
* For example, in '/foo/bar.tar.gz' the file name is 'bar'.
*/
static size_type FindName( const String& path );
/*!
* Finds a file extension in the specified \a path.
*
* Returns the character index position of the extension found, or
* String::notFound.
*
* The file extension, or file suffix, is the rightmost substring of \a path
* starting with the last occurrence of a dot character. For example, in
* 'foo.tar.gz' the file extension is '.gz'.
*
* \sa FindCompleteSuffix()
*/
static size_type FindExtension( const String& path );
/*!
* A synonym for FindExtension().
*/
static size_type FindSuffix( const String& path )
{
return FindExtension( path );
}
/*!
* Finds the complete file suffix in the specified \a path.
*
* Returns the character index position of the complete suffix found, or
* String::notFound.
*
* The complete suffix is the rightmost substring of the \a path starting
* with the first occurrence of a dot character. For example, in
* 'foo.tar.gz' the complete suffix is '.tar.gz'.
*
* \sa FindSuffix()
*/
static size_type FindCompleteSuffix( const String& path );
/*!
* Extracts a Windows drive specification from the specified \a path.
*
* Returns the extracted drive specification as a new string, or an empty
* string if no drive was found.
*
* This function only makes sense on Windows. On UNIX and Linux operating
* systems, this function always returns an empty string.
*/
static String ExtractDrive( const String& path ); // always empty string on X
/*!
* Extracts a directory specification from the specified \a path.
*
* Returns the extracted directory specification, or an empty string if no
* directory was found. On Windows, the drive element of the path is not
* included.
*
* Examples:
*
* In '/foo.tar.gz' the directory is '/'.
* In '/foo/bar.tar.gz' the directory is '/foo'.
* In 'foo/bar.tar.gz' the directory is 'foo'.
* In 'C:/Foo/Bar.txt' the directory is '/Foo'.
*/
static String ExtractDirectory( const String& path );
/*!
* Extracts a file name from the specified \a path.
*
* Returns the extracted name, or an empty string if no file name was found.
* The file extension or suffix is not included.
*
* Examples:
*
* In '/foo/bar.tar.gz' the name is 'bar.tar'.
* In 'C:/Foo/Bar.txt' the name is 'Bar'.
*/
static String ExtractName( const String& path );
/*!
* Extracts a file extension from the specified \a path.
*
* Returns the extracted extension, or an empty string if no file extension
* was found. The returned extension \e includes the initial dot separator.
*
* Examples:
*
* In '/foo/bar.tar.gz' the extension is '.gz'.
* In 'C:/Foo/Bar.txt' the extension is '.txt'.
*
* \sa ExtractCompleteSuffix()
*/
static String ExtractExtension( const String& path );
/*!
* A synonym for ExtractExtension().
*/
static String ExtractSuffix( const String& path )
{
return ExtractExtension( path );
}
/*!
* Extracts the complete file suffix from the specified \a path.
*
* Returns the extracted complete suffix, or an empty string if no file
* suffix was found. The returned string \e includes the initial dot
* separator.
*
* The complete suffix is the ending substring of the file identifier in the
* specified \a path, starting with the first occurrence of a dot character.
* For example, in 'foo.tar.gz' the complete suffix is '.tar.gz'.
*
* \sa ExtractSuffix()
*/
static String ExtractCompleteSuffix( const String& path );
/*!
* Extracts the file name and extension from the specified \a path. Calling
* this member function is functionally equivalent to:
*
* File::ExtractName( path ) + File::ExtractExtension( path )
*/
static String ExtractNameAndExtension( const String& path );
/*!
* A synonym for ExtractNameAndExtension().
*/
static String ExtractNameAndSuffix( const String& path )
{
return ExtractNameAndExtension( path );
}
/*!
* Changes the current file extension in \a filePath to a new extension
* \a ext. If it is not an empty string, the specified extension \e must
* include the initial dot separator.
*
* If the specified new extension \a ext is an empty string, this function
* returns \a filePath with its extension (if any) removed.
*
* Returns the resulting path after changing the file extension to the
* specified value.
*/
static String ChangeExtension( const String& filePath, const String& ext );
/*!
* Appends a \a postfix string to the current file name in the specified
* \a filePath. Returns the resulting path.
*/
static String AppendToName( const String& filePath, const String& postfix );
/*!
* Prepends a \a prefix string to the current file name in the specified
* \a filePath. Returns the resulting path.
*/
static String PrependToName( const String& filePath, const String& prefix );
/*!
* Returns a readable textual representation of a file size with automatic
* units conversion.
*
* \param sizeInBytes The file size in bytes.
*
* \param precision The number of decimal digits used to represent
* floating point numbers. The default value is 3.
*
* \param alsoShowBytes Whether to add the size in bytes to the string
* representation, irrespective of the units used. The
* default value is false.
*
* Examples:
*
* \code
* String s1 = File::SizeAsString( 21771472 );
* // s1 = "20.763 MiB"
* String s2 = File::SizeAsString( 21771472, 2, true );
* // s2 = "20.76 MiB (21771472 bytes)"
* String s3 = File::SizeAsString( 4727, 4 );
* // s3 = "4.6162 KiB"
* \endcode
*/
static String SizeAsString( fsize_type sizeInBytes, int precision = 3, bool alsoShowBytes = false );
protected:
handle m_fileHandle;
String m_filePath;
FileModes m_fileMode;
static const handle s_invalidHandle;
void Initialize();
virtual bool IsValidHandle( handle h ) const;
};
// ----------------------------------------------------------------------------
} // pcl
#endif // __PCL_File_h
// ----------------------------------------------------------------------------
// EOF pcl/File.h - Released 2022-03-12T18:59:29Z