DYT/Tool/OpenSceneGraph-3.6.5/include/cpl_vsi_virtual.h
2024-12-25 07:49:36 +08:00

581 lines
18 KiB
C++

/******************************************************************************
* $Id$
*
* Project: VSI Virtual File System
* Purpose: Declarations for classes related to the virtual filesystem.
* These would only be normally required by applications implementing
* their own virtual file system classes which should be rare.
* The class interface may be fragile through versions.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
* Copyright (c) 2010-2014, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT
****************************************************************************/
#ifndef CPL_VSI_VIRTUAL_H_INCLUDED
#define CPL_VSI_VIRTUAL_H_INCLUDED
#include "cpl_vsi.h"
#include "cpl_vsi_error.h"
#include "cpl_string.h"
#include "cpl_multiproc.h"
#include <map>
#include <memory>
#include <vector>
#include <string>
// To avoid aliasing to GetDiskFreeSpace to GetDiskFreeSpaceA on Windows
#ifdef GetDiskFreeSpace
#undef GetDiskFreeSpace
#endif
// To avoid aliasing to CopyFile to CopyFileA on Windows
#ifdef CopyFile
#undef CopyFile
#endif
/************************************************************************/
/* VSIVirtualHandle */
/************************************************************************/
/** Virtual file handle */
struct CPL_DLL VSIVirtualHandle
{
public:
virtual int Seek(vsi_l_offset nOffset, int nWhence) = 0;
virtual vsi_l_offset Tell() = 0;
virtual size_t Read(void *pBuffer, size_t nSize, size_t nCount) = 0;
virtual int ReadMultiRange(int nRanges, void **ppData,
const vsi_l_offset *panOffsets,
const size_t *panSizes);
/** This method is called when code plans to access soon one or several
* ranges in a file. Some file systems may be able to use this hint to
* for example asynchronously start such requests.
*
* Offsets may be given in a non-increasing order, and may potentially
* overlap.
*
* @param nRanges Size of the panOffsets and panSizes arrays.
* @param panOffsets Array containing the start offset of each range.
* @param panSizes Array containing the size (in bytes) of each range.
* @since GDAL 3.7
*/
virtual void AdviseRead(CPL_UNUSED int nRanges,
CPL_UNUSED const vsi_l_offset *panOffsets,
CPL_UNUSED const size_t *panSizes)
{
}
/** Return the total maximum number of bytes that AdviseRead() can handle
* at once.
*
* Some AdviseRead() implementations may give up if the sum of the values
* in the panSizes[] array provided to AdviseRead() exceeds a limit.
*
* Callers might use that threshold to optimize the efficiency of
* AdviseRead().
*
* A returned value of 0 indicates a unknown limit.
* @since GDAL 3.9
*/
virtual size_t GetAdviseReadTotalBytesLimit() const
{
return 0;
}
virtual size_t Write(const void *pBuffer, size_t nSize, size_t nCount) = 0;
int Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
CPL_PRINT_FUNC_FORMAT(2, 3);
virtual void ClearErr() = 0;
virtual int Eof() = 0;
virtual int Error() = 0;
virtual int Flush()
{
return 0;
}
virtual int Close() = 0;
// Base implementation that only supports file extension.
virtual int Truncate(vsi_l_offset nNewSize);
virtual void *GetNativeFileDescriptor()
{
return nullptr;
}
virtual VSIRangeStatus GetRangeStatus(CPL_UNUSED vsi_l_offset nOffset,
CPL_UNUSED vsi_l_offset nLength)
{
return VSI_RANGE_STATUS_UNKNOWN;
}
virtual bool HasPRead() const;
virtual size_t PRead(void *pBuffer, size_t nSize,
vsi_l_offset nOffset) const;
/** Ask current operations to be interrupted.
* Implementations must be thread-safe, as this will typically be called
* from another thread than the active one for this file.
*/
virtual void Interrupt()
{
}
// NOTE: when adding new methods, besides the "actual" implementations,
// also consider the VSICachedFile one.
virtual ~VSIVirtualHandle()
{
}
};
/************************************************************************/
/* VSIVirtualHandleCloser */
/************************************************************************/
/** Helper close to use with a std:unique_ptr<VSIVirtualHandle>,
* such as VSIVirtualHandleUniquePtr. */
struct VSIVirtualHandleCloser
{
/** Operator () that closes and deletes the file handle. */
void operator()(VSIVirtualHandle *poHandle)
{
if (poHandle)
{
poHandle->Close();
delete poHandle;
}
}
};
/** Unique pointer of VSIVirtualHandle that calls the Close() method */
typedef std::unique_ptr<VSIVirtualHandle, VSIVirtualHandleCloser>
VSIVirtualHandleUniquePtr;
/************************************************************************/
/* VSIFilesystemHandler */
/************************************************************************/
#ifndef DOXYGEN_SKIP
class CPL_DLL VSIFilesystemHandler
{
public:
virtual ~VSIFilesystemHandler()
{
}
VSIVirtualHandle *Open(const char *pszFilename, const char *pszAccess);
virtual VSIVirtualHandle *Open(const char *pszFilename,
const char *pszAccess, bool bSetError,
CSLConstList papszOptions) = 0;
virtual int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
int nFlags) = 0;
virtual int Unlink(const char *pszFilename)
{
(void)pszFilename;
errno = ENOENT;
return -1;
}
virtual int *UnlinkBatch(CSLConstList papszFiles);
virtual int Mkdir(const char *pszDirname, long nMode)
{
(void)pszDirname;
(void)nMode;
errno = ENOENT;
return -1;
}
virtual int Rmdir(const char *pszDirname)
{
(void)pszDirname;
errno = ENOENT;
return -1;
}
virtual int RmdirRecursive(const char *pszDirname);
char **ReadDir(const char *pszDirname)
{
return ReadDirEx(pszDirname, 0);
}
virtual char **ReadDirEx(const char * /*pszDirname*/, int /* nMaxFiles */)
{
return nullptr;
}
virtual char **SiblingFiles(const char * /*pszFilename*/)
{
return nullptr;
}
virtual int Rename(const char *oldpath, const char *newpath)
{
(void)oldpath;
(void)newpath;
errno = ENOENT;
return -1;
}
virtual int IsCaseSensitive(const char *pszFilename)
{
(void)pszFilename;
return TRUE;
}
virtual GIntBig GetDiskFreeSpace(const char * /* pszDirname */)
{
return -1;
}
virtual int SupportsSparseFiles(const char * /* pszPath */)
{
return FALSE;
}
virtual int HasOptimizedReadMultiRange(const char * /* pszPath */)
{
return FALSE;
}
virtual const char *GetActualURL(const char * /*pszFilename*/)
{
return nullptr;
}
virtual const char *GetOptions()
{
return nullptr;
}
virtual char *GetSignedURL(const char * /*pszFilename*/,
CSLConstList /* papszOptions */)
{
return nullptr;
}
virtual bool Sync(const char *pszSource, const char *pszTarget,
const char *const *papszOptions,
GDALProgressFunc pProgressFunc, void *pProgressData,
char ***ppapszOutputs);
virtual int CopyFile(const char *pszSource, const char *pszTarget,
VSILFILE *fpSource, vsi_l_offset nSourceSize,
const char *const *papszOptions,
GDALProgressFunc pProgressFunc, void *pProgressData);
virtual int
CopyFileRestartable(const char *pszSource, const char *pszTarget,
const char *pszInputPayload, char **ppszOutputPayload,
CSLConstList papszOptions,
GDALProgressFunc pProgressFunc, void *pProgressData);
virtual VSIDIR *OpenDir(const char *pszPath, int nRecurseDepth,
const char *const *papszOptions);
virtual char **GetFileMetadata(const char *pszFilename,
const char *pszDomain,
CSLConstList papszOptions);
virtual bool SetFileMetadata(const char *pszFilename,
CSLConstList papszMetadata,
const char *pszDomain,
CSLConstList papszOptions);
virtual bool
MultipartUploadGetCapabilities(int *pbNonSequentialUploadSupported,
int *pbParallelUploadSupported,
int *pbAbortSupported, size_t *pnMinPartSize,
size_t *pnMaxPartSize, int *pnMaxPartCount);
virtual char *MultipartUploadStart(const char *pszFilename,
CSLConstList papszOptions);
virtual char *MultipartUploadAddPart(const char *pszFilename,
const char *pszUploadId,
int nPartNumber,
vsi_l_offset nFileOffset,
const void *pData, size_t nDataLength,
CSLConstList papszOptions);
virtual bool
MultipartUploadEnd(const char *pszFilename, const char *pszUploadId,
size_t nPartIdsCount, const char *const *apszPartIds,
vsi_l_offset nTotalSize, CSLConstList papszOptions);
virtual bool MultipartUploadAbort(const char *pszFilename,
const char *pszUploadId,
CSLConstList papszOptions);
virtual bool AbortPendingUploads(const char * /*pszFilename*/)
{
return true;
}
virtual std::string
GetStreamingFilename(const std::string &osFilename) const
{
return osFilename;
}
virtual std::string
GetNonStreamingFilename(const std::string &osFilename) const
{
return osFilename;
}
/** Return the canonical filename.
*
* May be implemented by case-insensitive filesystems
* (currently Win32 and MacOSX)
* to return the filename with its actual case (i.e. the one that would
* be used when listing the content of the directory).
*/
virtual std::string
GetCanonicalFilename(const std::string &osFilename) const
{
return osFilename;
}
virtual bool IsLocal(const char * /* pszPath */)
{
return true;
}
virtual bool SupportsSequentialWrite(const char * /* pszPath */,
bool /* bAllowLocalTempFile */)
{
return true;
}
virtual bool SupportsRandomWrite(const char * /* pszPath */,
bool /* bAllowLocalTempFile */)
{
return true;
}
virtual bool SupportsRead(const char * /* pszPath */)
{
return true;
}
virtual VSIFilesystemHandler *Duplicate(const char * /* pszPrefix */)
{
CPLError(CE_Failure, CPLE_NotSupported,
"Duplicate() not supported on this file system");
return nullptr;
}
/** Return the directory separator.
*
* Default is forward slash. The only exception currently is the Windows
* file system which returns anti-slash, unless the specified path is of the
* form "{drive_letter}:/{rest_of_the_path}".
*/
virtual const char *GetDirectorySeparator(CPL_UNUSED const char *pszPath)
{
return "/";
}
};
#endif /* #ifndef DOXYGEN_SKIP */
/************************************************************************/
/* VSIFileManager */
/************************************************************************/
#ifndef DOXYGEN_SKIP
class CPL_DLL VSIFileManager
{
private:
VSIFilesystemHandler *poDefaultHandler = nullptr;
std::map<std::string, VSIFilesystemHandler *> oHandlers{};
VSIFileManager();
static VSIFileManager *Get();
CPL_DISALLOW_COPY_ASSIGN(VSIFileManager)
public:
~VSIFileManager();
static VSIFilesystemHandler *GetHandler(const char *);
static void InstallHandler(const std::string &osPrefix,
VSIFilesystemHandler *);
static void RemoveHandler(const std::string &osPrefix);
static char **GetPrefixes();
};
#endif /* #ifndef DOXYGEN_SKIP */
/************************************************************************/
/* ==================================================================== */
/* VSIArchiveFilesystemHandler */
/* ==================================================================== */
/************************************************************************/
#ifndef DOXYGEN_SKIP
class VSIArchiveEntryFileOffset
{
public:
virtual ~VSIArchiveEntryFileOffset();
};
typedef struct
{
char *fileName;
vsi_l_offset uncompressed_size;
VSIArchiveEntryFileOffset *file_pos;
int bIsDir;
GIntBig nModifiedTime;
} VSIArchiveEntry;
class VSIArchiveContent
{
public:
time_t mTime = 0;
vsi_l_offset nFileSize = 0;
int nEntries = 0;
VSIArchiveEntry *entries = nullptr;
~VSIArchiveContent();
};
class VSIArchiveReader
{
public:
virtual ~VSIArchiveReader();
virtual int GotoFirstFile() = 0;
virtual int GotoNextFile() = 0;
virtual VSIArchiveEntryFileOffset *GetFileOffset() = 0;
virtual GUIntBig GetFileSize() = 0;
virtual CPLString GetFileName() = 0;
virtual GIntBig GetModifiedTime() = 0;
virtual int GotoFileOffset(VSIArchiveEntryFileOffset *pOffset) = 0;
};
class VSIArchiveFilesystemHandler : public VSIFilesystemHandler
{
CPL_DISALLOW_COPY_ASSIGN(VSIArchiveFilesystemHandler)
protected:
CPLMutex *hMutex = nullptr;
/* We use a cache that contains the list of files contained in a VSIArchive
* file as */
/* unarchive.c is quite inefficient in listing them. This speeds up access
* to VSIArchive files */
/* containing ~1000 files like a CADRG product */
std::map<CPLString, VSIArchiveContent *> oFileList{};
virtual const char *GetPrefix() = 0;
virtual std::vector<CPLString> GetExtensions() = 0;
virtual VSIArchiveReader *CreateReader(const char *pszArchiveFileName) = 0;
public:
VSIArchiveFilesystemHandler();
virtual ~VSIArchiveFilesystemHandler();
int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
int nFlags) override;
int Unlink(const char *pszFilename) override;
int Rename(const char *oldpath, const char *newpath) override;
int Mkdir(const char *pszDirname, long nMode) override;
int Rmdir(const char *pszDirname) override;
char **ReadDirEx(const char *pszDirname, int nMaxFiles) override;
virtual const VSIArchiveContent *
GetContentOfArchive(const char *archiveFilename,
VSIArchiveReader *poReader = nullptr);
virtual char *SplitFilename(const char *pszFilename,
CPLString &osFileInArchive,
int bCheckMainFileExists);
virtual VSIArchiveReader *OpenArchiveFile(const char *archiveFilename,
const char *fileInArchiveName);
virtual int FindFileInArchive(const char *archiveFilename,
const char *fileInArchiveName,
const VSIArchiveEntry **archiveEntry);
virtual bool IsLocal(const char *pszPath) override;
virtual bool
SupportsSequentialWrite(const char * /* pszPath */,
bool /* bAllowLocalTempFile */) override
{
return false;
}
virtual bool SupportsRandomWrite(const char * /* pszPath */,
bool /* bAllowLocalTempFile */) override
{
return false;
}
};
/************************************************************************/
/* VSIDIR */
/************************************************************************/
struct CPL_DLL VSIDIR
{
VSIDIR() = default;
virtual ~VSIDIR();
virtual const VSIDIREntry *NextDirEntry() = 0;
private:
VSIDIR(const VSIDIR &) = delete;
VSIDIR &operator=(const VSIDIR &) = delete;
};
#endif /* #ifndef DOXYGEN_SKIP */
VSIVirtualHandle CPL_DLL *
VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle);
VSIVirtualHandle *
VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle,
const GByte *pabyBeginningContent,
vsi_l_offset nCheatFileSize);
constexpr int VSI_CACHED_DEFAULT_CHUNK_SIZE = 32768;
VSIVirtualHandle CPL_DLL *
VSICreateCachedFile(VSIVirtualHandle *poBaseHandle,
size_t nChunkSize = VSI_CACHED_DEFAULT_CHUNK_SIZE,
size_t nCacheSize = 0);
const int CPL_DEFLATE_TYPE_GZIP = 0;
const int CPL_DEFLATE_TYPE_ZLIB = 1;
const int CPL_DEFLATE_TYPE_RAW_DEFLATE = 2;
VSIVirtualHandle CPL_DLL *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
int nDeflateType,
int bAutoCloseBaseHandle);
VSIVirtualHandle *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
int nDeflateType,
bool bAutoCloseBaseHandle, int nThreads,
size_t nChunkSize,
size_t nSOZIPIndexEltSize,
std::vector<uint8_t> *panSOZIPIndex);
VSIVirtualHandle *
VSICreateUploadOnCloseFile(VSIVirtualHandleUniquePtr &&poWritableHandle,
VSIVirtualHandleUniquePtr &&poTmpFile,
const std::string &osTmpFilename);
#endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */