📄 cpl_vsi_mem.cpp
字号:
/******************************************************************************
* $Id: cpl_vsi_mem.cpp 11305 2007-04-20 16:31:38Z warmerdam $
*
* Project: VSI Virtual File System
* Purpose: Implementation of Memory Buffer virtual IO functions.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
/* Remove annoying warnings in eVC++ and VC++ 6.0 */
#if defined(WIN32CE)
# pragma warning(disable:4786)
#endif
#include "cpl_vsi_virtual.h"
#include "cpl_string.h"
#include "cpl_multiproc.h"
#include <map>
#if defined(WIN32CE)
# include <wce_errno.h>
#endif
CPL_CVSID("$Id: cpl_vsi_mem.cpp 11305 2007-04-20 16:31:38Z warmerdam $");
/*
** Notes on Multithreading:
**
** VSIMemFilesystemHandler: This class maintains a mutex to protect
** access and update of the oFileList array which has all the "files" in
** the memory filesystem area. It is expected that multiple threads would
** want to create and read different files at the same time and so might
** collide access oFileList without the mutex.
**
** VSIMemFile: In theory we could allow different threads to update the
** the same memory file, but for simplicity we restrict to single writer,
** multiple reader as an expectation on the application code (not enforced
** here), which means we don't need to do any protection of this class.
**
** VSIMemHandle: This is essentially a "current location" representing
** on accessor to a file, and is inherently intended only to be used in
** a single thread.
**
** In General:
**
** Multiple threads accessing the memory filesystem are ok as long as
** 1) A given VSIMemHandle (ie. FILE * at app level) isn't used by multiple
** threads at once.
** 2) A given memory file isn't accessed by more than one thread unless
** all threads are just reading.
*/
/************************************************************************/
/* ==================================================================== */
/* VSIMemFile */
/* ==================================================================== */
/************************************************************************/
class VSIMemFile
{
public:
CPLString osFilename;
int nRefCount;
int bIsDirectory;
int bOwnData;
GByte *pabyData;
vsi_l_offset nLength;
vsi_l_offset nAllocLength;
VSIMemFile();
virtual ~VSIMemFile();
bool SetLength( vsi_l_offset nNewSize );
};
/************************************************************************/
/* ==================================================================== */
/* VSIMemHandle */
/* ==================================================================== */
/************************************************************************/
class VSIMemHandle : public VSIVirtualHandle
{
public:
VSIMemFile *poFile;
vsi_l_offset nOffset;
virtual int Seek( vsi_l_offset nOffset, int nWhence );
virtual vsi_l_offset Tell();
virtual size_t Read( void *pBuffer, size_t nSize, size_t nMemb );
virtual size_t Write( const void *pBuffer, size_t nSize, size_t nMemb );
virtual int Eof();
virtual int Close();
};
/************************************************************************/
/* ==================================================================== */
/* VSIMemFilesystemHandler */
/* ==================================================================== */
/************************************************************************/
class VSIMemFilesystemHandler : public VSIFilesystemHandler
{
public:
std::map<CPLString,VSIMemFile*> oFileList;
void *hMutex;
VSIMemFilesystemHandler();
virtual ~VSIMemFilesystemHandler();
virtual VSIVirtualHandle *Open( const char *pszFilename,
const char *pszAccess);
virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf );
virtual int Unlink( const char *pszFilename );
virtual int Mkdir( const char *pszDirname, long nMode );
virtual int Rmdir( const char *pszDirname );
virtual char **ReadDir( const char *pszDirname );
};
/************************************************************************/
/* ==================================================================== */
/* VSIMemFile */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* VSIMemFile() */
/************************************************************************/
VSIMemFile::VSIMemFile()
{
nRefCount = 0;
bIsDirectory = FALSE;
bOwnData = TRUE;
pabyData = NULL;
nLength = 0;
nAllocLength = 0;
}
/************************************************************************/
/* ~VSIMemFile() */
/************************************************************************/
VSIMemFile::~VSIMemFile()
{
if( nRefCount != 0 )
CPLDebug( "VSIMemFile", "Memory file %s deleted with %d references.",
osFilename.c_str(), nRefCount );
if( bOwnData && pabyData )
CPLFree( pabyData );
}
/************************************************************************/
/* SetLength() */
/************************************************************************/
bool VSIMemFile::SetLength( vsi_l_offset nNewLength )
{
/* -------------------------------------------------------------------- */
/* Grow underlying array if needed. */
/* -------------------------------------------------------------------- */
if( nNewLength > nAllocLength )
{
GByte *pabyNewData;
vsi_l_offset nNewAlloc = (nNewLength + nNewLength / 10) + 5000;
pabyNewData = (GByte *) CPLRealloc(pabyData, (size_t)nNewAlloc);
if( pabyNewData == NULL )
return false;
pabyData = pabyNewData;
nAllocLength = nNewAlloc;
}
nLength = nNewLength;
return true;
}
/************************************************************************/
/* ==================================================================== */
/* VSIMemHandle */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* Close() */
/************************************************************************/
int VSIMemHandle::Close()
{
poFile->nRefCount--;
poFile = NULL;
return 0;
}
/************************************************************************/
/* Seek() */
/************************************************************************/
int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
{
if( nWhence == SEEK_CUR )
this->nOffset += nOffset;
else if( nWhence == SEEK_SET )
this->nOffset = nOffset;
else if( nWhence == SEEK_END )
this->nOffset = poFile->nLength + nOffset;
else
{
errno = EINVAL;
return -1;
}
if( this->nOffset < 0 )
{
this->nOffset = 0;
return -1;
}
if( this->nOffset > poFile->nLength )
{
if( !poFile->SetLength( this->nOffset ) )
return -1;
}
return 0;
}
/************************************************************************/
/* Tell() */
/************************************************************************/
vsi_l_offset VSIMemHandle::Tell()
{
return nOffset;
}
/************************************************************************/
/* Read() */
/************************************************************************/
size_t VSIMemHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
{
// FIXME: Integer overflow check should be placed here:
size_t nBytesToRead = nSize * nCount;
if( nBytesToRead + nOffset > poFile->nLength )
{
nBytesToRead = poFile->nLength - nOffset;
nCount = nBytesToRead / nSize;
}
memcpy( pBuffer, poFile->pabyData + nOffset, (size_t)nBytesToRead );
nOffset += nBytesToRead;
return nCount;
}
/************************************************************************/
/* Write() */
/************************************************************************/
size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount )
{
// FIXME: Integer overflow check should be placed here:
size_t nBytesToWrite = nSize * nCount;
if( nBytesToWrite + nOffset > poFile->nLength )
{
if( !poFile->SetLength( nBytesToWrite + nOffset ) )
return 0;
}
memcpy( poFile->pabyData + nOffset, pBuffer, nBytesToWrite );
nOffset += nBytesToWrite;
return nCount;
}
/************************************************************************/
/* Eof() */
/************************************************************************/
int VSIMemHandle::Eof()
{
return nOffset == poFile->nLength;
}
/************************************************************************/
/* ==================================================================== */
/* VSIMemFilesystemHandler */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* VSIMemFilesystemHandler() */
/************************************************************************/
VSIMemFilesystemHandler::VSIMemFilesystemHandler()
{
hMutex = NULL;
}
/************************************************************************/
/* ~VSIMemFilesystemHandler() */
/************************************************************************/
VSIMemFilesystemHandler::~VSIMemFilesystemHandler()
{
std::map<CPLString,VSIMemFile*>::const_iterator iter;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -