📄 cpl_vsi_mem.cpp
字号:
for( iter = oFileList.begin(); iter != oFileList.end(); iter++ )
delete iter->second;
if( hMutex != NULL )
CPLDestroyMutex( hMutex );
hMutex = NULL;
}
/************************************************************************/
/* Open() */
/************************************************************************/
VSIVirtualHandle *
VSIMemFilesystemHandler::Open( const char *pszFilename,
const char *pszAccess )
{
CPLMutexHolder oHolder( &hMutex );
VSIMemFile *poFile;
/* -------------------------------------------------------------------- */
/* Get the filename we are opening, create if needed. */
/* -------------------------------------------------------------------- */
if( oFileList.find(pszFilename) == oFileList.end() )
poFile = NULL;
else
poFile = oFileList[pszFilename];
if( strstr(pszAccess,"w") == NULL && poFile == NULL )
{
errno = ENOENT;
return NULL;
}
if( strstr(pszAccess,"w") )
{
if( poFile )
poFile->SetLength( 0 );
else
{
poFile = new VSIMemFile;
poFile->osFilename = pszFilename;
oFileList[poFile->osFilename] = poFile;
}
}
if( poFile->bIsDirectory )
{
errno = EISDIR;
return NULL;
}
/* -------------------------------------------------------------------- */
/* Setup the file handle on this file. */
/* -------------------------------------------------------------------- */
VSIMemHandle *poHandle = new VSIMemHandle;
poHandle->poFile = poFile;
poHandle->nOffset = 0;
poFile->nRefCount++;
if( strstr(pszAccess,"a") )
poHandle->nOffset = poFile->nLength;
return poHandle;
}
/************************************************************************/
/* Stat() */
/************************************************************************/
int VSIMemFilesystemHandler::Stat( const char * pszFilename,
VSIStatBufL * pStatBuf )
{
CPLMutexHolder oHolder( &hMutex );
if( oFileList.find(pszFilename) == oFileList.end() )
{
errno = ENOENT;
return -1;
}
VSIMemFile *poFile = oFileList[pszFilename];
memset( pStatBuf, 0, sizeof(VSIStatBufL) );
if( poFile->bIsDirectory )
{
pStatBuf->st_size = 0;
pStatBuf->st_mode = S_IFDIR;
}
else
{
pStatBuf->st_size = poFile->nLength;
pStatBuf->st_mode = S_IFREG;
}
return 0;
}
/************************************************************************/
/* Unlink() */
/************************************************************************/
int VSIMemFilesystemHandler::Unlink( const char * pszFilename )
{
CPLMutexHolder oHolder( &hMutex );
VSIMemFile *poFile;
if( oFileList.find(pszFilename) == oFileList.end() )
{
errno = ENOENT;
return -1;
}
else
{
poFile = oFileList[pszFilename];
delete poFile;
oFileList.erase( oFileList.find(pszFilename) );
return 0;
}
}
/************************************************************************/
/* Mkdir() */
/************************************************************************/
int VSIMemFilesystemHandler::Mkdir( const char * pszPathname,
long nMode )
{
CPLMutexHolder oHolder( &hMutex );
if( oFileList.find(pszPathname) != oFileList.end() )
{
errno = EEXIST;
return -1;
}
VSIMemFile *poFile = new VSIMemFile;
poFile->osFilename = pszPathname;
poFile->bIsDirectory = TRUE;
oFileList[pszPathname] = poFile;
return 0;
}
/************************************************************************/
/* Rmdir() */
/************************************************************************/
int VSIMemFilesystemHandler::Rmdir( const char * pszPathname )
{
CPLMutexHolder oHolder( &hMutex );
return Unlink( pszPathname );
}
/************************************************************************/
/* ReadDir() */
/************************************************************************/
char **VSIMemFilesystemHandler::ReadDir( const char *pszPath )
{
return NULL;
}
/************************************************************************/
/* VSIInstallLargeFileHandler() */
/************************************************************************/
/**
* \brief Install "memory" file system handler.
*
* A special file handler is installed that allows block of memory to be
* treated as files. All portions of the file system underneath the base
* path "/vsimem/" will be handled by this driver.
*
* Normal VSI*L functions can be used freely to create and destroy memory
* arrays treating them as if they were real file system objects. Some
* additional methods exist to efficient create memory file system objects
* without duplicating original copies of the data or to "steal" the block
* of memory associated with a memory file.
*
* At this time the memory handler does not properly handle directory
* semantics for the memory portion of the filesystem. The VSIReadDir()
* function is not supported though this will be corrected in the future.
*
* Calling this function repeatedly should do no harm, though it is not
* necessary. It is already called the first time a virtualizable
* file access function (ie. VSIFOpenL(), VSIMkDir(), etc) is called.
*
* This code example demonstrates using GDAL to translate from one memory
* buffer to another.
*
* \code
* GByte *ConvertBufferFormat( GByte *pabyInData, vsi_l_offset nInDataLength,
* vsi_l_offset *pnOutDataLength )
* {
* // create memory file system object from buffer.
* VSIFCloseL( VSIFileFromMemBuffer( "/vsimem/work.dat", pabyInData,
* nInDataLength, FALSE ) );
*
* // Open memory buffer for read.
* GDALDatasetH hDS = GDALOpen( "/vsimem/work.dat", GA_ReadOnly );
*
* // Get output format driver.
* GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
* GDALDatasetH hOutDS;
*
* hOutDS = GDALCreateCopy( hDriver, "/vsimem/out.tif", hDS, TRUE, NULL,
* NULL, NULL );
*
* // close source file, and "unlink" it.
* GDALClose( hDS );
* VSIUnlink( "/vsimem/work.dat" );
*
* // seize the buffer associated with the output file.
*
* return VSIGetMemFileBuffer( "/vsimem/out.tif", pnOutDataLength, TRUE );
* }
* \endcode
*/
void VSIInstallMemFileHandler()
{
VSIFileManager::InstallHandler( std::string("/vsimem/"),
new VSIMemFilesystemHandler );
}
/************************************************************************/
/* VSIFileFromMemBuffer() */
/************************************************************************/
/**
* \brief Create memory "file" from a buffer.
*
* A virtual memory file is created from the passed buffer with the indicated
* filename. Under normal conditions the filename would need to be absolute
* and within the /vsimem/ portion of the filesystem.
*
* If bTakeOwnership is TRUE, then the memory file system handler will take
* ownership of the buffer, freeing it when the file is deleted. Otherwise
* it remains the responsibility of the caller, but should not be freed as
* long as it might be accessed as a file. In no circumstances does this
* function take a copy of the pabyData contents.
*
* @param pszFilename the filename to be created.
* @param pabyData the data buffer for the file.
* @param nDataLength the length of buffer in bytes.
* @param bTakeOwnership TRUE to transfer "ownership" of buffer or FALSE.
*
* @return open file handle on created file (see VSIFOpenL()).
*/
FILE *VSIFileFromMemBuffer( const char *pszFilename,
GByte *pabyData,
vsi_l_offset nDataLength,
int bTakeOwnership )
{
if( VSIFileManager::GetHandler("")
== VSIFileManager::GetHandler("/vsimem/") )
VSIInstallMemFileHandler();
VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *)
VSIFileManager::GetHandler("/vsimem/");
VSIMemFile *poFile = new VSIMemFile;
poFile->osFilename = pszFilename;
poFile->bOwnData = bTakeOwnership;
poFile->pabyData = pabyData;
poFile->nLength = nDataLength;
poFile->nAllocLength = nDataLength;
{
CPLMutexHolder oHolder( &poHandler->hMutex );
poHandler->oFileList[poFile->osFilename] = poFile;
}
return (FILE *) poHandler->Open( pszFilename, "r+" );
}
/************************************************************************/
/* VSIGetMemFileBuffer() */
/************************************************************************/
/**
* \brief Fetch buffer underlying memory file.
*
* This function returns a pointer to the memory buffer underlying a
* virtual "in memory" file. If bUnlinkAndSeize is TRUE the filesystem
* object will be deleted, and ownership of the buffer will pass to the
* caller otherwise the underlying file will remain in existance.
*
* @param pszFilename the name of the file to grab the buffer of.
* @param buffer (file) length returned in this variable.
* @param bUnlinkAndSeize TRUE to remove the file, or FALSE to leave unaltered.
*
* @return pointer to memory buffer or NULL on failure.
*/
GByte *VSIGetMemFileBuffer( const char *pszFilename,
vsi_l_offset *pnDataLength,
int bUnlinkAndSeize )
{
VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *)
VSIFileManager::GetHandler("/vsimem/");
CPLMutexHolder oHolder( &poHandler->hMutex );
if( poHandler->oFileList.find(pszFilename) == poHandler->oFileList.end() )
return NULL;
VSIMemFile *poFile = poHandler->oFileList[pszFilename];
GByte *pabyData;
pabyData = poFile->pabyData;
if( pnDataLength != NULL )
*pnDataLength = poFile->nLength;
if( bUnlinkAndSeize )
{
if( !poFile->bOwnData )
CPLDebug( "VSIMemFile",
"File doesn't own data in VSIGetMemFileBuffer!" );
else
poFile->bOwnData = FALSE;
delete poFile;
poHandler->oFileList.erase( poHandler->oFileList.find(pszFilename) );
}
return pabyData;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -