mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +02:00
- Added missing projects "VFS" & "export" to SVN
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4447 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
|
||||
## Aspects
|
||||
|
||||
set(INCLUDE_Aspects
|
||||
${MOD_INCLUDE}/vfs_logging.h
|
||||
${MOD_INCLUDE}/vfs_settings.h
|
||||
${MOD_INCLUDE}/vfs_synchronization.h
|
||||
)
|
||||
set(SOURCE_Aspects
|
||||
${MOD_SOURCE}/vfs_logging.cpp
|
||||
${MOD_SOURCE}/vfs_settings.cpp
|
||||
${MOD_SOURCE}/vfs_synchronization.cpp
|
||||
)
|
||||
source_group( "Aspects" FILES ${INCLUDE_Aspects} ${SOURCE_Aspects} )
|
||||
|
||||
set(${mod}_files
|
||||
${INCLUDE_Aspects} ${SOURCE_Aspects}
|
||||
CACHE INTERNAL ""
|
||||
)
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* bfVFS : vfs/Aspects/vfs_logging.cpp
|
||||
* - Logging interface and macros that will be used to report errors/warnings to the using program
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Aspects/vfs_logging.h>
|
||||
#include <vfs/Core/vfs_string.h>
|
||||
|
||||
static vfs::Aspects::ILogger* s_LogDebug = 0;
|
||||
static vfs::Aspects::ILogger* s_LogInfo = 0;
|
||||
static vfs::Aspects::ILogger* s_LogWarning = 0;
|
||||
static vfs::Aspects::ILogger* s_LogError = 0;
|
||||
|
||||
void vfs::Aspects::setLogger( ILogger* info_logger, ILogger* warning_logger, ILogger* error_logger, ILogger* debug_logger )
|
||||
{
|
||||
setLogger(LOG_INFO, info_logger);
|
||||
setLogger(LOG_WARNING, warning_logger);
|
||||
setLogger(LOG_ERROR, error_logger);
|
||||
setLogger(LOG_DEBUG, debug_logger);
|
||||
}
|
||||
|
||||
|
||||
void vfs::Aspects::setLogger(vfs::Aspects::LogType type, vfs::Aspects::ILogger* logger)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case vfs::Aspects::LOG_INFO :
|
||||
s_LogInfo = logger;
|
||||
break;
|
||||
case vfs::Aspects::LOG_WARNING :
|
||||
s_LogWarning = logger;
|
||||
break;
|
||||
case vfs::Aspects::LOG_ERROR :
|
||||
s_LogError = logger;
|
||||
break;
|
||||
case vfs::Aspects::LOG_DEBUG :
|
||||
s_LogDebug = logger;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::Aspects::ILogger* vfs::Aspects::getLogger(vfs::Aspects::LogType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case vfs::Aspects::LOG_DEBUG : return s_LogDebug;
|
||||
case vfs::Aspects::LOG_INFO : return s_LogInfo;
|
||||
case vfs::Aspects::LOG_WARNING : return s_LogWarning;
|
||||
case vfs::Aspects::LOG_ERROR : return s_LogError;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vfs::Aspects::Debug(vfs::String const& msg)
|
||||
{
|
||||
if(s_LogDebug)
|
||||
{
|
||||
s_LogDebug->Msg(msg.c_str());
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Debug(const wchar_t* msg)
|
||||
{
|
||||
if(s_LogDebug)
|
||||
{
|
||||
s_LogDebug->Msg(msg);
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Debug(const char* msg)
|
||||
{
|
||||
if(s_LogDebug)
|
||||
{
|
||||
s_LogDebug->Msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void vfs::Aspects::Info(vfs::String const& msg)
|
||||
{
|
||||
if(s_LogInfo)
|
||||
{
|
||||
s_LogInfo->Msg(msg.c_str());
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Info(const wchar_t* msg)
|
||||
{
|
||||
if(s_LogInfo)
|
||||
{
|
||||
s_LogInfo->Msg(msg);
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Info(const char* msg)
|
||||
{
|
||||
if(s_LogInfo)
|
||||
{
|
||||
s_LogInfo->Msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::Aspects::Warning(vfs::String const& msg)
|
||||
{
|
||||
if(s_LogWarning)
|
||||
{
|
||||
s_LogWarning->Msg(msg.c_str());
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Warning(const wchar_t* msg)
|
||||
{
|
||||
if(s_LogWarning)
|
||||
{
|
||||
s_LogWarning->Msg(msg);
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Warning(const char* msg)
|
||||
{
|
||||
if(s_LogWarning)
|
||||
{
|
||||
s_LogWarning->Msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::Aspects::Error(vfs::String const& msg)
|
||||
{
|
||||
if(s_LogError)
|
||||
{
|
||||
s_LogError->Msg(msg.c_str());
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Error(const wchar_t* msg)
|
||||
{
|
||||
if(s_LogError)
|
||||
{
|
||||
s_LogError->Msg(msg);
|
||||
}
|
||||
}
|
||||
void vfs::Aspects::Error(const char* msg)
|
||||
{
|
||||
if(s_LogError)
|
||||
{
|
||||
s_LogError->Msg(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* bfVFS : vfs/Aspects/vfs_settings.cpp
|
||||
* - library runtime settings,
|
||||
* - e.g., to use Unicode strings or regular for file names
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Aspects/vfs_settings.h>
|
||||
|
||||
static bool s_UseUnicode = true;
|
||||
|
||||
void vfs::Settings::setUseUnicode(bool useUnicode)
|
||||
{
|
||||
s_UseUnicode = useUnicode;
|
||||
}
|
||||
|
||||
bool vfs::Settings::getUseUnicode()
|
||||
{
|
||||
return s_UseUnicode;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* bfVFS : vfs/Aspects/vfs_synchronization.cpp
|
||||
* - Interface for Mutexes and Locks, implementation can or has to be provided by the using program
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Aspects/vfs_synchronization.h>
|
||||
|
||||
static vfs::Aspects::IMutexFactory* s_mutex_factory = 0;
|
||||
|
||||
void vfs::Aspects::setMutexFactory(IMutexFactory* mutex_factory)
|
||||
{
|
||||
s_mutex_factory = mutex_factory;
|
||||
}
|
||||
vfs::Aspects::IMutexFactory* vfs::Aspects::getMutexFactory()
|
||||
{
|
||||
return s_mutex_factory;
|
||||
}
|
||||
|
||||
|
||||
vfs::Aspects::Mutex::Mutex() : _locked(0)
|
||||
{
|
||||
if(s_mutex_factory)
|
||||
{
|
||||
_mutex = s_mutex_factory->createMutex();
|
||||
}
|
||||
else
|
||||
{
|
||||
_mutex = new IMutex();
|
||||
}
|
||||
}
|
||||
|
||||
vfs::Aspects::Mutex::~Mutex()
|
||||
{
|
||||
if(_mutex)
|
||||
{
|
||||
_mutex->unlock();
|
||||
delete _mutex;
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::Aspects::Mutex::lock()
|
||||
{
|
||||
_mutex->lock();
|
||||
_locked++;
|
||||
}
|
||||
|
||||
void vfs::Aspects::Mutex::unlock()
|
||||
{
|
||||
if(_locked > 0)
|
||||
{
|
||||
_locked--;
|
||||
_mutex->unlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
####################################################
|
||||
|
||||
set(INCLUDE_bfvfs_config
|
||||
${BFVFS_INCLUDE_DIR}/vfs/vfs_config.h
|
||||
)
|
||||
source_group("" FILES ${INCLUDE_bfvfs_config})
|
||||
|
||||
set(BFVFS_files ${INCLUDE_bfvfs_config})
|
||||
|
||||
|
||||
##
|
||||
## iterate over bfVFS modules and add files
|
||||
##
|
||||
set(BFVFS_MODULES "Aspects" "Core" "Ext" "Tools")
|
||||
|
||||
foreach(mod ${BFVFS_MODULES})
|
||||
set( MOD_INCLUDE ${BFVFS_INCLUDE_DIR}/vfs/${mod} )
|
||||
set( MOD_SOURCE ${mod} )
|
||||
|
||||
include( ${mod}/files.cmake )
|
||||
set(BFVFS_files ${BFVFS_files} ${${mod}_files})
|
||||
endforeach()
|
||||
|
||||
if(BFVFS_WITH_7ZIP)
|
||||
set(DEFINITIONS ${DEFINITIONS} "-DVFS_WITH_7ZIP")
|
||||
add_definitions(-DVFS_WITH_7ZIP ${BFVFS_7ZIP_DEFINITIONS})
|
||||
include_directories(${BFVFS_7ZIP_DIR}/src)
|
||||
endif()
|
||||
|
||||
if(BFVFS_WITH_SLF)
|
||||
set(DEFINITIONS ${DEFINITIONS} "-DVFS_WITH_SLF")
|
||||
add_definitions(-DVFS_WITH_SLF)
|
||||
endif()
|
||||
|
||||
####################################################
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if(BUILD_BFVFS_SHARED)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
add_definitions(-DVFS_EXPORT)
|
||||
set(DEFINITIONS ${DEFINITIONS} -DVFS_IMPORT)
|
||||
else()
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
add_definitions(-DVFS_STATIC)
|
||||
set(DEFINITIONS ${DEFINITIONS} -DVFS_STATIC)
|
||||
endif()
|
||||
|
||||
set(BFVFS_TARGET "bfVFS" CACHE INTERNAL "")
|
||||
add_library( ${BFVFS_TARGET} ${BFVFS_files} )
|
||||
|
||||
set_property(
|
||||
TARGET ${BFVFS_TARGET}
|
||||
PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${BFVFS_LIBRARY_DIRS}
|
||||
)
|
||||
set_property(
|
||||
TARGET ${BFVFS_TARGET}
|
||||
PROPERTY LIBRARY_OUTPUT_DIRECTORY ${BFVFS_LIBRARY_DIRS}
|
||||
)
|
||||
set_property(
|
||||
TARGET ${BFVFS_TARGET}
|
||||
PROPERTY RUNTIME_OUTPUT_DIRECTORY ${BFVFS_RUNTIME_DIRS}
|
||||
)
|
||||
|
||||
if(BUILD_BFVFS_SHARED)
|
||||
if(MINGW)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-enable-auto-import")
|
||||
endif()
|
||||
|
||||
if(BFVFS_WITH_7ZIP)
|
||||
target_link_libraries(${BFVFS_TARGET} ${BFVFS_7ZIP_TARGET})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(BFVFS_VFS_DEFINITIONS ${DEFINITIONS} CACHE INTERNAL "")
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/File/vfs_buffer_file.cpp
|
||||
* - Buffer in RAM, implements File interface to unify usage of file and memory
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/File/vfs_buffer_file.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define ERROR_FILE(msg) (_BS(L"[") << this->getPath() << L"] - " << (msg) << _BS::wget)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define IS_FILE_VALID() VFS_THROW_IFF( m_buffer.good(), ERROR_FILE(L"invalid file object") );
|
||||
#else
|
||||
#define IS_FILE_VALID() VFS_THROW_IFF( m_buffer.good(), ERROR_FILE(L"invalid file object") );
|
||||
#endif
|
||||
|
||||
static inline std::ios::seekdir _seekDir(vfs::IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
if(seekDir == vfs::IBaseFile::SD_BEGIN)
|
||||
{
|
||||
return std::ios::beg;
|
||||
}
|
||||
else if(seekDir == vfs::IBaseFile::SD_CURRENT)
|
||||
{
|
||||
return std::ios::cur;
|
||||
}
|
||||
else if(seekDir == vfs::IBaseFile::SD_END)
|
||||
{
|
||||
return std::ios::end;
|
||||
}
|
||||
VFS_THROW(_BS(L"Unknown seek direction [") << seekDir << L"]" << _BS::wget);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
vfs::CBufferFile::CBufferFile()
|
||||
: tBaseClass(vfs::Path()), m_isOpen_read(false), m_isOpen_write(false)
|
||||
{
|
||||
m_buffer.str("");
|
||||
}
|
||||
|
||||
vfs::CBufferFile::CBufferFile(vfs::Path const& fileName)
|
||||
: tBaseClass(fileName), m_isOpen_read(false), m_isOpen_write(false)
|
||||
{
|
||||
m_buffer.str("");
|
||||
}
|
||||
|
||||
vfs::CBufferFile::~CBufferFile()
|
||||
{
|
||||
m_buffer.str("");
|
||||
m_buffer.clear();
|
||||
}
|
||||
|
||||
vfs::FileAttributes vfs::CBufferFile::getAttributes()
|
||||
{
|
||||
return vfs::FileAttributes(vfs::FileAttributes::ATTRIB_NORMAL, vfs::FileAttributes::LT_NONE);
|
||||
}
|
||||
|
||||
void vfs::CBufferFile::close()
|
||||
{
|
||||
m_buffer.clear();
|
||||
m_isOpen_read = false;
|
||||
m_isOpen_write = false;
|
||||
IS_FILE_VALID();
|
||||
}
|
||||
vfs::size_t vfs::CBufferFile::getSize()
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
|
||||
std::streampos size = 0;
|
||||
if(!m_buffer.str().empty())
|
||||
{
|
||||
std::streampos current_position = m_buffer.tellg();
|
||||
m_buffer.seekg(0,std::ios::end);
|
||||
size = m_buffer.tellg();
|
||||
m_buffer.seekg(current_position,std::ios::beg);
|
||||
}
|
||||
|
||||
IS_FILE_VALID();
|
||||
return (vfs::size_t)size;
|
||||
}
|
||||
|
||||
bool vfs::CBufferFile::isOpenRead()
|
||||
{
|
||||
return m_isOpen_read;
|
||||
}
|
||||
|
||||
bool vfs::CBufferFile::openRead()
|
||||
{
|
||||
if(!m_buffer.good())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return m_isOpen_read = true;
|
||||
}
|
||||
vfs::size_t vfs::CBufferFile::read(vfs::Byte* data, vfs::size_t bytesToRead)
|
||||
{
|
||||
if(!m_buffer.eof())
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF(m_isOpen_read || this->openRead(), ERROR_FILE(L"open error"));
|
||||
|
||||
m_buffer.read(static_cast<Byte*>(data), bytesToRead);
|
||||
std::streamsize bytesRead = m_buffer.gcount();
|
||||
|
||||
VFS_THROW_IFF( m_buffer.good() || m_buffer.eof(), ERROR_FILE(L"read error") );
|
||||
return (vfs::size_t)bytesRead;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CBufferFile::getReadPosition()
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF(m_isOpen_read || this->openRead(), ERROR_FILE(L"open error"));
|
||||
|
||||
return (vfs::size_t)m_buffer.tellg();
|
||||
}
|
||||
|
||||
void vfs::CBufferFile::setReadPosition(vfs::size_t positionInBytes)
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF( m_isOpen_read || this->openRead(), ERROR_FILE(L"open error") );
|
||||
|
||||
m_buffer.seekg((std::streamoff)positionInBytes);
|
||||
|
||||
IS_FILE_VALID();
|
||||
}
|
||||
void vfs::CBufferFile::setReadPosition(vfs::offset_t offsetInBytes, IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF( m_isOpen_read || this->openRead(), ERROR_FILE(L"open error") );
|
||||
|
||||
std::ios::seekdir ioSeekDir;
|
||||
VFS_TRYCATCH_RETHROW(ioSeekDir = _seekDir(seekDir), ERROR_FILE(L"seek error"));
|
||||
m_buffer.seekg(offsetInBytes, ioSeekDir);
|
||||
|
||||
IS_FILE_VALID();
|
||||
}
|
||||
|
||||
bool vfs::CBufferFile::isOpenWrite()
|
||||
{
|
||||
return m_isOpen_write;
|
||||
}
|
||||
|
||||
bool vfs::CBufferFile::openWrite(bool bCreateWhenNotExist, bool bTruncate)
|
||||
{
|
||||
if( !m_buffer.good() )
|
||||
return false;
|
||||
if( m_isOpen_write )
|
||||
return true;
|
||||
|
||||
if(bTruncate)
|
||||
{
|
||||
m_buffer.str("");
|
||||
m_buffer.clear();
|
||||
}
|
||||
m_isOpen_write = m_buffer.good();
|
||||
return m_isOpen_write;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CBufferFile::write(const vfs::Byte* data, vfs::size_t bytesToWrite)
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF( m_isOpen_write || this->openWrite(), ERROR_FILE(L"open error") );
|
||||
|
||||
std::streampos start = 0;
|
||||
if(!m_buffer.str().empty())
|
||||
{
|
||||
start = m_buffer.tellp();
|
||||
}
|
||||
VFS_THROW_IFF( m_buffer.write(data, bytesToWrite), ERROR_FILE(L"write error") );
|
||||
std::streampos bytesWritten = m_buffer.tellp() - start;
|
||||
|
||||
IS_FILE_VALID();
|
||||
|
||||
return (vfs::size_t)bytesWritten;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CBufferFile::getWritePosition()
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF( m_isOpen_write || this->openWrite(), ERROR_FILE(L"open error") );
|
||||
|
||||
return (vfs::size_t)m_buffer.tellp();
|
||||
}
|
||||
|
||||
void vfs::CBufferFile::setWritePosition(vfs::size_t positionInBytes)
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF( m_isOpen_write || this->openWrite(), ERROR_FILE(L"open error") );
|
||||
|
||||
m_buffer.seekp((std::streamoff)positionInBytes);
|
||||
|
||||
IS_FILE_VALID();
|
||||
}
|
||||
|
||||
void vfs::CBufferFile::setWritePosition(vfs::offset_t offsetInBytes, IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
IS_FILE_VALID();
|
||||
VFS_THROW_IFF( m_isOpen_write || this->openWrite(), ERROR_FILE(L"open error") );
|
||||
|
||||
std::ios::seekdir ioSeekDir;
|
||||
VFS_TRYCATCH_RETHROW( ioSeekDir = _seekDir(seekDir), ERROR_FILE(L"seek error") );
|
||||
m_buffer.seekp(offsetInBytes, ioSeekDir);
|
||||
|
||||
IS_FILE_VALID();
|
||||
}
|
||||
|
||||
void vfs::CBufferFile::copyToBuffer(vfs::tReadableFile& rFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool needToClose = !rFile.isOpenRead();
|
||||
vfs::COpenReadFile readfile(&rFile);
|
||||
if(!needToClose)
|
||||
{
|
||||
readfile.release();
|
||||
}
|
||||
|
||||
typedef std::vector<vfs::Byte> tByteVector;
|
||||
|
||||
vfs::size_t size = rFile.getSize();
|
||||
if(size > 0)
|
||||
{
|
||||
tByteVector vBuffer(size);
|
||||
|
||||
rFile.read(&vBuffer[0], size);
|
||||
this->write(&vBuffer[0], size);
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(ERROR_FILE(L""), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool vfs::CBufferFile::deleteFile()
|
||||
{
|
||||
m_buffer.clear();
|
||||
m_buffer.str("");
|
||||
return m_buffer.good();
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/File/vfs_dir_file.cpp
|
||||
* - read/read-write files for usage in vfs locations (directories)
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/File/vfs_dir_file.h>
|
||||
#include <vfs/Core/Interface/vfs_directory_interface.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
|
||||
#include <vfs/Aspects/vfs_settings.h>
|
||||
|
||||
vfs::CReadOnlyDirFile::CReadOnlyDirFile(vfs::Path const& filename, tLocation *directory)
|
||||
: vfs::CReadOnlyFile(filename), _location(directory)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CReadOnlyDirFile::~CReadOnlyDirFile()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::Path vfs::CReadOnlyDirFile::getPath()
|
||||
{
|
||||
if(_location)
|
||||
{
|
||||
return _location->getPath() + m_filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::CReadOnlyDirFile::_getRealPath(vfs::Path& path)
|
||||
{
|
||||
if(_location)
|
||||
{
|
||||
path = _location->getRealPath() + m_filename;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
vfs::FileAttributes vfs::CReadOnlyDirFile::getAttributes()
|
||||
{
|
||||
vfs::FileAttributes _attribs = vfs::CReadOnlyFile::getAttributes();
|
||||
|
||||
vfs::UInt32 attr = _attribs.getAttrib();
|
||||
attr |= vfs::FileAttributes::ATTRIB_READONLY;
|
||||
|
||||
return vfs::FileAttributes(attr, vfs::FileAttributes::LT_READONLY_DIRECTORY);
|
||||
}
|
||||
|
||||
bool vfs::CReadOnlyDirFile::openRead()
|
||||
{
|
||||
vfs::Path filename;
|
||||
if(!_getRealPath(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _internalOpenRead(filename);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vfs::CDirFile::CDirFile(vfs::Path const& filename, tLocation *directory)
|
||||
: CFile(filename), _location(directory)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CDirFile::~CDirFile()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::Path vfs::CDirFile::getPath()
|
||||
{
|
||||
if(_location)
|
||||
{
|
||||
return _location->getPath() + m_filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::CDirFile::deleteFile()
|
||||
{
|
||||
this->close();
|
||||
vfs::Path fname;
|
||||
if(_getRealPath(fname))
|
||||
{
|
||||
return vfs::OS::deleteRealFile(fname);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool vfs::CDirFile::_getRealPath(vfs::Path& path)
|
||||
{
|
||||
if(_location)
|
||||
{
|
||||
path = _location->getRealPath() + m_filename;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
vfs::FileAttributes vfs::CDirFile::getAttributes()
|
||||
{
|
||||
vfs::FileAttributes _attribs = vfs::CFile::getAttributes();
|
||||
|
||||
return vfs::FileAttributes(_attribs.getAttrib(), vfs::FileAttributes::LT_DIRECTORY);
|
||||
}
|
||||
|
||||
bool vfs::CDirFile::openRead()
|
||||
{
|
||||
vfs::Path filename;
|
||||
if(!_getRealPath(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _internalOpenRead(filename);
|
||||
}
|
||||
|
||||
bool vfs::CDirFile::openWrite(bool createWhenNotExist, bool truncate)
|
||||
{
|
||||
vfs::Path filename;
|
||||
if(!_getRealPath(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _internalOpenWrite(filename, createWhenNotExist, truncate);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,619 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/File/vfs_file.cpp
|
||||
* - File with read/read-write access
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
|
||||
#include <vfs/Aspects/vfs_settings.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define ERROR_FILE(msg) (_BS(L"[") << this->getPath() << L"] - " << (msg) << _BS::wget)
|
||||
|
||||
static inline bool hasAttrib(vfs::UInt32 const& attrib, vfs::UInt32 Attribs)
|
||||
{
|
||||
return attrib == (attrib & Attribs);
|
||||
}
|
||||
|
||||
static inline void copyAttributes(vfs::UInt32 osFileAttributes, vfs::UInt32& vfsFileAttributes)
|
||||
{
|
||||
if(vfs::OS::FileAttributes::ATTRIB_ARCHIVE == (vfs::OS::FileAttributes::ATTRIB_ARCHIVE & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_ARCHIVE;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_COMPRESSED == (vfs::OS::FileAttributes::ATTRIB_COMPRESSED & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_COMPRESSED;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_DIRECTORY == (vfs::OS::FileAttributes::ATTRIB_DIRECTORY & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_DIRECTORY;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_HIDDEN == (vfs::OS::FileAttributes::ATTRIB_HIDDEN & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_HIDDEN;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_NORMAL == (vfs::OS::FileAttributes::ATTRIB_NORMAL & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_NORMAL;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_OFFLINE == (vfs::OS::FileAttributes::ATTRIB_OFFLINE & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_OFFLINE;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_READONLY == (vfs::OS::FileAttributes::ATTRIB_READONLY & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_READONLY;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_SYSTEM == (vfs::OS::FileAttributes::ATTRIB_SYSTEM & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_SYSTEM;
|
||||
}
|
||||
if(vfs::OS::FileAttributes::ATTRIB_TEMPORARY == (vfs::OS::FileAttributes::ATTRIB_TEMPORARY & osFileAttributes))
|
||||
{
|
||||
vfsFileAttributes |= vfs::FileAttributes::ATTRIB_TEMPORARY;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static inline DWORD _seekDir(vfs::IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
if(seekDir == vfs::IBaseFile::SD_BEGIN)
|
||||
{
|
||||
return FILE_BEGIN;
|
||||
}
|
||||
else if(seekDir == vfs::IBaseFile::SD_CURRENT)
|
||||
{
|
||||
return FILE_CURRENT;
|
||||
}
|
||||
else if(seekDir == vfs::IBaseFile::SD_END)
|
||||
{
|
||||
return FILE_END;
|
||||
}
|
||||
VFS_THROW(_BS(L"Unknown seek direction [") << seekDir << L"]" << _BS::wget);
|
||||
}
|
||||
#else
|
||||
static inline int _seekDir(vfs::IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
if(seekDir == vfs::IBaseFile::SD_BEGIN)
|
||||
{
|
||||
return SEEK_SET;
|
||||
}
|
||||
else if(seekDir == vfs::IBaseFile::SD_CURRENT)
|
||||
{
|
||||
return SEEK_CUR;
|
||||
}
|
||||
else if(seekDir == vfs::IBaseFile::SD_END)
|
||||
{
|
||||
return SEEK_END;
|
||||
}
|
||||
VFS_THROW(_BS(L"Unknown seek direction [") << seekDir << L"]" << _BS::wget);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TFile<WriteType>::TFile(vfs::Path const& filename)
|
||||
: tBaseClass(filename), m_isOpen_read(false), m_file(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TFile<WriteType>::~TFile()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
#ifndef WIN32
|
||||
if(m_file)clearerr(m_file);
|
||||
#endif
|
||||
if(m_isOpen_read)
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TFile<WriteType>::close()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
if(m_file)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(!CloseHandle(m_file))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"Could not close file : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
//clearerr(m_file);
|
||||
fflush(m_file);
|
||||
int error = fclose(m_file);
|
||||
if(error)
|
||||
{
|
||||
//const char* error_str = perror(error);
|
||||
VFS_THROW( ERROR_FILE(_BS(L"Could not close file : ") << error << _BS::wget) );
|
||||
}
|
||||
#endif
|
||||
m_file = NULL;
|
||||
}
|
||||
m_isOpen_read = false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::FileAttributes vfs::TFile<WriteType>::getAttributes()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
vfs::Path fullpath;
|
||||
VFS_THROW_IFF(this->_getRealPath(fullpath), ERROR_FILE(L""));
|
||||
|
||||
vfs::UInt32 osFileAttributes = 0;
|
||||
vfs::OS::FileAttributes fa;
|
||||
VFS_THROW_IFF( fa.getFileAttributes(fullpath, osFileAttributes), ERROR_FILE(L"Could not read file attributes") );
|
||||
|
||||
vfs::UInt32 _attribs = vfs::FileAttributes::ATTRIB_INVALID;
|
||||
copyAttributes(osFileAttributes, _attribs);
|
||||
|
||||
if(!this->implementsWritable())
|
||||
{
|
||||
_attribs &= ~vfs::FileAttributes::ATTRIB_NORMAL;
|
||||
_attribs |= vfs::FileAttributes::ATTRIB_READONLY;
|
||||
}
|
||||
|
||||
return vfs::FileAttributes(_attribs, vfs::FileAttributes::LT_NONE);
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TFile<WriteType>::isOpenRead()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
return m_isOpen_read;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TFile<WriteType>::_internalOpenRead(vfs::Path const& path)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
if( m_isOpen_read )
|
||||
return true;
|
||||
#ifdef WIN32
|
||||
m_file = vfs::Settings::getUseUnicode() ?
|
||||
CreateFileW(path.c_str(),GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL) :
|
||||
CreateFileA(vfs::String::narrow(path.c_str(),path.length()).c_str(),GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR && err != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
VFS_LOG_ERROR( ERROR_FILE(_BS(L"Error when opening file : ") << err << _BS::wget) );
|
||||
return m_isOpen_read = false;
|
||||
}
|
||||
return m_isOpen_read = true;
|
||||
#else
|
||||
m_file = fopen(path.to_string().c_str(), "r");
|
||||
return m_isOpen_read = (m_file != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TFile<WriteType>::openRead()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
return _internalOpenRead(this->m_filename);
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::size_t vfs::TFile<WriteType>::read(vfs::Byte* pData, vfs::size_t bytesToRead)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
DWORD has_read = 0;
|
||||
if(!ReadFile(m_file, pData, bytesToRead, &has_read, NULL))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR && err != ERROR_HANDLE_EOF)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"read error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
size_t has_read = fread(pData,1,bytesToRead,m_file);
|
||||
if(has_read != bytesToRead)
|
||||
{
|
||||
int error = ferror(m_file);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"read error : ") << error << _BS::wget) );
|
||||
}
|
||||
clearerr(m_file);
|
||||
}
|
||||
#endif
|
||||
return has_read;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::size_t vfs::TFile<WriteType>::getReadPosition()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER current_position,zero;
|
||||
zero.QuadPart = 0;
|
||||
if(!SetFilePointerEx(m_file, zero, ¤t_position, FILE_CURRENT))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
return (vfs::size_t)current_position.QuadPart;
|
||||
#else
|
||||
long int pos = ftell(m_file);
|
||||
if(pos == -1L)
|
||||
{
|
||||
int error = ferror(m_file);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << error << _BS::wget) );
|
||||
}
|
||||
}
|
||||
return (vfs::size_t)pos;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TFile<WriteType>::setReadPosition(vfs::size_t positionInBytes)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER pos;
|
||||
pos.QuadPart = positionInBytes;
|
||||
if(!SetFilePointerEx(m_file, pos, NULL, FILE_BEGIN))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
int error = fseek(m_file,positionInBytes,SEEK_SET);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << error << _BS::wget) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TFile<WriteType>::setReadPosition(vfs::offset_t offsetInBytes, IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
DWORD ioSeekDir;
|
||||
VFS_TRYCATCH_RETHROW( ioSeekDir = _seekDir(seekDir), ERROR_FILE(L"seek error"));
|
||||
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = offsetInBytes;
|
||||
if(!SetFilePointerEx(m_file, offset, NULL, ioSeekDir))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
int ioSeekDir;
|
||||
VFS_TRYCATCH_RETHROW( ioSeekDir = _seekDir(seekDir), ERROR_FILE(L"seek error"));
|
||||
int error = fseek(m_file, offsetInBytes, ioSeekDir);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << error << _BS::wget) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
|
||||
vfs::CFile::CFile(vfs::Path const& filename)
|
||||
: tBaseClass(filename), m_isOpen_write(false)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CFile::~CFile()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
if(m_isOpen_read || m_isOpen_write)
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::CFile::close()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
tBaseClass::close();
|
||||
m_isOpen_write = false;
|
||||
}
|
||||
|
||||
bool vfs::CFile::deleteFile()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
this->close();
|
||||
return vfs::OS::deleteRealFile(m_filename);
|
||||
}
|
||||
|
||||
bool vfs::CFile::isOpenWrite()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
return m_isOpen_write;
|
||||
}
|
||||
|
||||
bool vfs::CFile::_internalOpenWrite(vfs::Path const& path, bool createWhenNotExist, bool truncate)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
if( m_isOpen_write )
|
||||
return true;
|
||||
#ifdef WIN32
|
||||
DWORD Mode = 0;
|
||||
if(createWhenNotExist)
|
||||
{
|
||||
Mode |= OPEN_ALWAYS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Mode |= OPEN_EXISTING;
|
||||
}
|
||||
if(truncate)
|
||||
{
|
||||
Mode |= TRUNCATE_EXISTING;
|
||||
}
|
||||
|
||||
m_file = vfs::Settings::getUseUnicode() ?
|
||||
CreateFileW(path.c_str(),GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,Mode,FILE_ATTRIBUTE_NORMAL,NULL) :
|
||||
CreateFileA(vfs::String::narrow(path.c_str(),path.length()).c_str(),GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,Mode,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
DWORD err = GetLastError();
|
||||
if(truncate && err == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
Mode = CREATE_ALWAYS;
|
||||
m_file = vfs::Settings::getUseUnicode() ?
|
||||
CreateFileW(path.c_str(),GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,Mode,FILE_ATTRIBUTE_NORMAL,NULL) :
|
||||
CreateFileA(vfs::String::narrow(path.c_str(),path.length()).c_str(),GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,Mode,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
err = GetLastError();
|
||||
}
|
||||
if(err != NO_ERROR && err != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
VFS_LOG_ERROR(_BS(L"Error when opening file - ") << path << L" - [" << err << L"]" << _BS::wget);
|
||||
return m_isOpen_write = false;
|
||||
}
|
||||
return m_isOpen_write = true;
|
||||
#else
|
||||
m_file = fopen(path.to_string().c_str(), "r+");
|
||||
if( (!m_file && createWhenNotExist) || (m_file && truncate))
|
||||
{
|
||||
m_file = fopen(path.to_string().c_str(), "w");
|
||||
}
|
||||
|
||||
return m_isOpen_write = (m_file != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool vfs::CFile::openWrite(bool createWhenNotExist, bool truncate)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
return _internalOpenWrite(m_filename, createWhenNotExist, truncate);
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CFile::write(const vfs::Byte* data, vfs::size_t bytesToWrite)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_write, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
DWORD has_written = 0;
|
||||
if(!WriteFile(m_file, data, bytesToWrite, &has_written, NULL))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW(_BS(L"write error : ") << err << _BS::wget);
|
||||
}
|
||||
}
|
||||
#else
|
||||
size_t has_written = fwrite(data, 1, bytesToWrite, m_file);
|
||||
if(has_written != bytesToWrite)
|
||||
{
|
||||
int error = ferror(m_file);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW(_BS(L"write error : ") << error << _BS::wget);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return (vfs::size_t)has_written;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CFile::getWritePosition()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_write, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER current_position, zero;
|
||||
zero.QuadPart = 0;
|
||||
if(!SetFilePointerEx(m_file, zero, ¤t_position, FILE_CURRENT))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
return (vfs::size_t)current_position.QuadPart;
|
||||
#else
|
||||
long int pos = ftell(m_file);
|
||||
if(pos == -1L)
|
||||
{
|
||||
int error = ferror(m_file);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << error << _BS::wget) );
|
||||
}
|
||||
}
|
||||
return (vfs::size_t)pos;
|
||||
#endif
|
||||
}
|
||||
|
||||
void vfs::CFile::setWritePosition(vfs::size_t positionInBytes)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_write, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER pos;
|
||||
pos.QuadPart = positionInBytes;
|
||||
if(!SetFilePointerEx(m_file, pos, NULL, FILE_CURRENT))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
int error = fseek(m_file,positionInBytes,SEEK_SET);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << error << _BS::wget) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void vfs::CFile::setWritePosition(vfs::offset_t offsetInBytes, vfs::IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
VFS_THROW_IFF( m_isOpen_write, ERROR_FILE(L"file not opened") );
|
||||
#ifdef WIN32
|
||||
DWORD ioSeekDir;
|
||||
VFS_TRYCATCH_RETHROW( ioSeekDir = _seekDir(seekDir), ERROR_FILE(L"seek error"));
|
||||
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = offsetInBytes;
|
||||
if(!SetFilePointerEx(m_file, offset, NULL, ioSeekDir))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
int ioSeekDir;
|
||||
VFS_TRYCATCH_RETHROW( ioSeekDir = _seekDir(seekDir), ERROR_FILE(L"seek error"));
|
||||
int error = fseek(m_file, offsetInBytes, ioSeekDir);
|
||||
if(error)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"set position error : ") << error << _BS::wget) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
vfs::size_t vfs::TFile<T>::getSize()
|
||||
{
|
||||
//VFS_LOCK(m_mutex);
|
||||
#ifdef WIN32
|
||||
bool was_open = false;
|
||||
if(m_file)
|
||||
{
|
||||
was_open = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW_IFF(this->openRead(),ERROR_FILE(L"could not open file"));
|
||||
}
|
||||
vfs::size_t size;
|
||||
# ifdef _MSC_VER
|
||||
LARGE_INTEGER li_size;
|
||||
if(!GetFileSizeEx(m_file, &li_size))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"get size error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
size = (vfs::size_t)li_size.QuadPart;
|
||||
# else
|
||||
DWORD low_part, high_part;
|
||||
low_part = GetFileSize(m_file, &high_part);
|
||||
if(low_part == INVALID_FILE_SIZE)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(_BS(L"get size error : ") << err << _BS::wget) );
|
||||
}
|
||||
}
|
||||
size = low_part;
|
||||
# endif
|
||||
if(!was_open)
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
return size;
|
||||
#else
|
||||
// if file was alredy opened, keep it open, otherwise close it
|
||||
bool closeAtExit = !m_isOpen_read;
|
||||
|
||||
VFS_THROW_IFF( m_isOpen_read || this->openRead(), ERROR_FILE(L"could not open file") )
|
||||
|
||||
// save current position
|
||||
long int current_position = ftell(m_file);
|
||||
|
||||
// move to end of the file
|
||||
fseek(m_file, 0, SEEK_END);
|
||||
long int file_size = ftell(m_file);
|
||||
|
||||
// move to old position
|
||||
fseek(m_file, current_position, SEEK_SET);
|
||||
VFS_THROW_IFF(current_position == ftell(m_file), ERROR_FILE(L"could not restore seek position"));
|
||||
|
||||
if(closeAtExit)
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
return (vfs::size_t)file_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/******************************************************************/
|
||||
|
||||
template class vfs::TFile<vfs::IWriteType>;
|
||||
template class vfs::TFile<vfs::IWritable>;
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/File/vfs_lib_file.cpp
|
||||
* - read/read-write files for usage in vfs locations (libraries)
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/File/vfs_lib_file.h>
|
||||
#include <vfs/Core/vfs.h>
|
||||
|
||||
|
||||
#define ERROR_FILE(msg) (_BS(L"[") << this->getPath()() << L"] - " << msg << _BS::wget)
|
||||
|
||||
vfs::ObjBlockAllocator<vfs::CLibFile>* vfs::CLibFile::_lfile_pool = NULL;
|
||||
|
||||
vfs::CLibFile* vfs::CLibFile::create(vfs::Path const& filename,
|
||||
tLocation *location,
|
||||
ILibrary *library,
|
||||
vfs::ObjBlockAllocator<vfs::CLibFile>* allocator)
|
||||
{
|
||||
#if 0
|
||||
vfs::CLibFile* pFile = new vfs::CLibFile();
|
||||
#else
|
||||
vfs::CLibFile* pFile;
|
||||
if(allocator)
|
||||
{
|
||||
pFile = allocator->New();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!_lfile_pool)
|
||||
{
|
||||
_lfile_pool = new vfs::ObjBlockAllocator<vfs::CLibFile>();
|
||||
vfs::ObjectAllocator::registerAllocator(_lfile_pool);
|
||||
}
|
||||
pFile = _lfile_pool->New();
|
||||
}
|
||||
#endif
|
||||
pFile->m_filename = filename;
|
||||
pFile->m_location = location;
|
||||
pFile->m_library = library;
|
||||
return pFile;
|
||||
}
|
||||
|
||||
vfs::CLibFile::CLibFile()
|
||||
: tBaseClass(L""),
|
||||
m_isOpen_read(false),
|
||||
m_library(NULL),
|
||||
m_location(NULL)
|
||||
{
|
||||
};
|
||||
|
||||
vfs::CLibFile::~CLibFile()
|
||||
{
|
||||
}
|
||||
|
||||
void vfs::CLibFile::close()
|
||||
{
|
||||
if(m_isOpen_read)
|
||||
{
|
||||
m_library->close(this);
|
||||
m_isOpen_read = false;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::FileAttributes vfs::CLibFile::getAttributes()
|
||||
{
|
||||
return vfs::FileAttributes(vfs::FileAttributes::ATTRIB_NORMAL | vfs::FileAttributes::ATTRIB_READONLY,
|
||||
vfs::FileAttributes::LT_LIBRARY);
|
||||
}
|
||||
|
||||
vfs::Path vfs::CLibFile::getPath()
|
||||
{
|
||||
if(m_location)
|
||||
{
|
||||
return m_location->getPath() + m_filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
}
|
||||
bool vfs::CLibFile::isOpenRead()
|
||||
{
|
||||
return m_isOpen_read;
|
||||
}
|
||||
|
||||
bool vfs::CLibFile::openRead()
|
||||
{
|
||||
if(!m_isOpen_read)
|
||||
{
|
||||
VFS_TRYCATCH_RETHROW(m_isOpen_read = m_library->openRead(this), ERROR_FILE(L"read open error"));
|
||||
}
|
||||
return m_isOpen_read;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CLibFile::read(vfs::Byte* data, vfs::size_t bytesToRead)
|
||||
{
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
try
|
||||
{
|
||||
return m_library->read(this, data, bytesToRead);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(ERROR_FILE(L"read error"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CLibFile::getReadPosition()
|
||||
{
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
try
|
||||
{
|
||||
return m_library->getReadPosition(this);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(ERROR_FILE(L"library error"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void vfs::CLibFile::setReadPosition(vfs::size_t uiPositionInBytes)
|
||||
{
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
VFS_TRYCATCH_RETHROW(m_library->setReadPosition(this,uiPositionInBytes), ERROR_FILE(L"library error") );
|
||||
}
|
||||
|
||||
void vfs::CLibFile::setReadPosition(vfs::offset_t offsetInBytes, IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
VFS_THROW_IFF( m_isOpen_read, ERROR_FILE(L"file not opened") );
|
||||
VFS_TRYCATCH_RETHROW(m_library->setReadPosition(this, offsetInBytes, seekDir), ERROR_FILE(L"library error"));
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CLibFile::getSize()
|
||||
{
|
||||
VFS_THROW_IFF( m_isOpen_read || this->openRead(), ERROR_FILE(L"could not open file") );
|
||||
try
|
||||
{
|
||||
return m_library->getSize(this);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(ERROR_FILE(L"library error"), ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Interface/vfs_interface_members.cpp
|
||||
* - non-generic code from the interface header files
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Interface/vfs_file_interface.h>
|
||||
#include <vfs/Core/Interface/vfs_library_interface.h>
|
||||
|
||||
/**********************************************************************
|
||||
* vfs::FileAttributes
|
||||
*/
|
||||
vfs::FileAttributes::FileAttributes()
|
||||
: _attribs(ATTRIB_NORMAL), _location(LT_NONE)
|
||||
{
|
||||
};
|
||||
|
||||
vfs::FileAttributes::FileAttributes(vfs::UInt32 attribs, LocationType location)
|
||||
: _attribs(attribs), _location(location)
|
||||
{
|
||||
};
|
||||
|
||||
vfs::UInt32 vfs::FileAttributes::getAttrib() const
|
||||
{
|
||||
return _attribs;
|
||||
};
|
||||
|
||||
vfs::UInt32 vfs::FileAttributes::getLocation() const
|
||||
{
|
||||
return _location;
|
||||
};
|
||||
|
||||
bool vfs::FileAttributes::isAttribSet(vfs::UInt32 attribs) const
|
||||
{
|
||||
return attribs == (attribs & _attribs);
|
||||
};
|
||||
|
||||
bool vfs::FileAttributes::isAttribNotSet(vfs::UInt32 attribs) const
|
||||
{
|
||||
return 0 == (attribs & _attribs);
|
||||
};
|
||||
|
||||
bool vfs::FileAttributes::isLocation(vfs::UInt32 location) const
|
||||
{
|
||||
return location == (location & _location);
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* vfs::IBaseFile
|
||||
*/
|
||||
|
||||
vfs::IBaseFile::IBaseFile(vfs::Path const& filename)
|
||||
: m_filename(filename)
|
||||
{};
|
||||
|
||||
vfs::IBaseFile::~IBaseFile()
|
||||
{};
|
||||
|
||||
vfs::Path const& vfs::IBaseFile::getName()
|
||||
{
|
||||
return m_filename;
|
||||
};
|
||||
|
||||
vfs::Path vfs::IBaseFile::getPath()
|
||||
{
|
||||
return this->getName();
|
||||
};
|
||||
|
||||
|
||||
bool vfs::IBaseFile::_getRealPath(vfs::Path& path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* vfs::ILibrary
|
||||
*/
|
||||
|
||||
vfs::ILibrary::ILibrary(vfs::tReadableFile *libraryFile, vfs::Path const& mountPoint, bool ownFile)
|
||||
: tBaseClass(mountPoint), m_ownLibFile(ownFile), m_libraryFile(libraryFile)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::ILibrary::~ILibrary()
|
||||
{
|
||||
if(m_libraryFile && m_ownLibFile)
|
||||
{
|
||||
m_libraryFile->close();
|
||||
delete m_libraryFile;
|
||||
m_libraryFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::Path const& vfs::ILibrary::getName()
|
||||
{
|
||||
return m_libraryFile->getName();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Location/vfs_directory_tree.cpp
|
||||
* - class for directories in a File System, implements Directory interface
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Location/vfs_directory_tree.h>
|
||||
#include <vfs/Core/File/vfs_dir_file.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#define ERROR_FILE(msg) (_BS(msg) << L" : " << pFile->getPath() << _BS::wget)
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
template<typename WriteType>
|
||||
class TSubDir : public vfs::TDirectory<typename vfs::TDirectoryTree<WriteType>::tWriteType>
|
||||
{
|
||||
typedef vfs::TDirectory<typename vfs::TDirectoryTree<WriteType>::tWriteType> tBaseClass;
|
||||
typedef typename tBaseClass::tFileType tFileType;
|
||||
|
||||
typedef std::map<vfs::Path, tFileType*, vfs::Path::Less> tFileCatalogue;
|
||||
public:
|
||||
typedef vfs::IBaseLocation::Iterator Iterator;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
class IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
friend class TSubDir<WriteType>;
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
|
||||
IterImpl(TSubDir<WriteType>* dir): _dir(dir)
|
||||
{
|
||||
VFS_THROW_IFF(_dir, L"");
|
||||
_iter = _dir->m_mapFiles.begin();
|
||||
}
|
||||
public:
|
||||
IterImpl() : tBaseClass(), _dir(NULL)
|
||||
{};
|
||||
virtual ~IterImpl()
|
||||
{};
|
||||
|
||||
virtual tFileType* value()
|
||||
{
|
||||
if(_iter != _dir->m_mapFiles.end())
|
||||
{
|
||||
return _iter->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void next()
|
||||
{
|
||||
if(_iter != _dir->m_mapFiles.end())
|
||||
{
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl();
|
||||
iter->_dir = _dir;
|
||||
iter->_iter = _iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
TSubDir<WriteType>* _dir;
|
||||
typename tFileCatalogue::iterator _iter;
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
TSubDir(vfs::Path const& sMountPoint, vfs::Path const& sRealPath)
|
||||
: tBaseClass(sMountPoint,sRealPath)
|
||||
{};
|
||||
|
||||
virtual ~TSubDir();
|
||||
|
||||
virtual bool fileExists(vfs::Path const& rFileName);
|
||||
virtual vfs::IBaseFile* getFile(vfs::Path const& rFileName);
|
||||
virtual tFileType* getFileTyped(vfs::Path const& rFileName);
|
||||
|
||||
virtual tFileType* addFile(vfs::Path const& sFilename, bool bDeleteOldFile=false);
|
||||
virtual bool addFile(tFileType* pFile, bool bDeleteOldFile=false);
|
||||
|
||||
virtual bool createSubDirectory(vfs::Path const& sSubDirPath);
|
||||
virtual bool deleteDirectory(vfs::Path const& sDirPath);
|
||||
virtual bool deleteFileFromDirectory(vfs::Path const& sFileName);
|
||||
|
||||
virtual void getSubDirList(std::list<vfs::Path>& rlSubDirs);
|
||||
|
||||
virtual Iterator begin();
|
||||
private:
|
||||
tFileCatalogue m_mapFiles;
|
||||
};
|
||||
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWriteType>::tFileType* vfs::TSubDir<vfs::IWriteType>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile);
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWritable>::tFileType* vfs::TSubDir<vfs::IWritable>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile);
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteDirectory(vfs::Path const& sDirPath);
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteDirectory(vfs::Path const& sDirPath);
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteFileFromDirectory(vfs::Path const& rFileName);
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteFileFromDirectory(vfs::Path const& rFileName);
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TSubDir<WriteType>::~TSubDir()
|
||||
{
|
||||
typename tFileCatalogue::iterator it = m_mapFiles.begin();
|
||||
for(; it != m_mapFiles.end(); ++it)
|
||||
{
|
||||
if(it->second)
|
||||
{
|
||||
it->second->close();
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
m_mapFiles.clear();
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TSubDir<WriteType>::fileExists(vfs::Path const& sFileName)
|
||||
{
|
||||
typename tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
|
||||
bool success = (it != m_mapFiles.end()) && (it->second != NULL);
|
||||
return success;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::IBaseFile* vfs::TSubDir<WriteType>::getFile(vfs::Path const& sFileName)
|
||||
{
|
||||
return getFileTyped(sFileName);
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TSubDir<WriteType>::tFileType* vfs::TSubDir<WriteType>::getFileTyped(vfs::Path const& sFileName)
|
||||
{
|
||||
typename tFileCatalogue::iterator it = m_mapFiles.find(sFileName);
|
||||
if(it != m_mapFiles.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWriteType>::tFileType* vfs::TSubDir<vfs::IWriteType>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile)
|
||||
{
|
||||
tFileType* pFile = m_mapFiles[sFilename];
|
||||
if(pFile)
|
||||
{
|
||||
if(!bDeleteOldFile)
|
||||
{
|
||||
// not allowed to replace old file
|
||||
return NULL;
|
||||
}
|
||||
delete pFile;
|
||||
}
|
||||
pFile = new vfs::CReadOnlyDirFile(sFilename,this);
|
||||
m_mapFiles[sFilename] = pFile;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
template<>
|
||||
vfs::TSubDir<vfs::IWritable>::tFileType* vfs::TSubDir<vfs::IWritable>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile)
|
||||
{
|
||||
tFileType* pFile = m_mapFiles[sFilename];
|
||||
if(pFile)
|
||||
{
|
||||
if(!bDeleteOldFile)
|
||||
{
|
||||
// not allowed to replace old file
|
||||
return NULL;
|
||||
}
|
||||
delete pFile;
|
||||
}
|
||||
pFile = new vfs::CDirFile(sFilename,this);
|
||||
m_mapFiles[sFilename] = pFile;
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TSubDir<WriteType>::addFile(tFileType* pFile, bool bDeleteOldFile)
|
||||
{
|
||||
if(!pFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tFileType* pOldFile = m_mapFiles[pFile->getName()];
|
||||
if( pOldFile && (pOldFile != pFile) )
|
||||
{
|
||||
if(bDeleteOldFile)
|
||||
{
|
||||
pOldFile->close();
|
||||
delete pOldFile;
|
||||
}
|
||||
}
|
||||
m_mapFiles[pFile->getName()] = pFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteDirectory(vfs::Path const& sDirPath)
|
||||
{
|
||||
if( !(this->m_mountPoint == sDirPath) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
tFileCatalogue::iterator it = m_mapFiles.begin();
|
||||
for(; it != m_mapFiles.end(); ++it)
|
||||
{
|
||||
tFileType* pFile = it->second;
|
||||
if(pFile)
|
||||
{
|
||||
pFile->close();
|
||||
if(!pFile->deleteFile())
|
||||
{
|
||||
VFS_THROW( ERROR_FILE(L"Could not delete file") );
|
||||
}
|
||||
delete pFile;
|
||||
}
|
||||
}
|
||||
m_mapFiles.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteDirectory(vfs::Path const& sDirPath)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWritable>::deleteFileFromDirectory(vfs::Path const& rFileName)
|
||||
{
|
||||
tFileCatalogue::iterator it = m_mapFiles.find(rFileName);
|
||||
if( it != m_mapFiles.end() )
|
||||
{
|
||||
tFileType* pFile = it->second;
|
||||
if(pFile)
|
||||
{
|
||||
pFile->close();
|
||||
VFS_THROW_IFF(pFile->deleteFile(), ERROR_FILE(L"Could not delete file"));
|
||||
delete pFile;
|
||||
}
|
||||
m_mapFiles.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool vfs::TSubDir<vfs::IWriteType>::deleteFileFromDirectory(vfs::Path const& rFileName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TSubDir<WriteType>::createSubDirectory(vfs::Path const& sSubDirPath)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TSubDir<WriteType>::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TSubDir<WriteType>::Iterator vfs::TSubDir<WriteType>::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(this));
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
template<typename WriteType>
|
||||
class vfs::TDirectoryTree<WriteType>::IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
typedef vfs::TDirectoryTree<WriteType> tDirTree;
|
||||
public:
|
||||
IterImpl(tDirTree& tree);
|
||||
virtual ~IterImpl();
|
||||
|
||||
virtual typename tDirTree::tFileType* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl(_tree);
|
||||
iter->_subdir_iter = _subdir_iter;
|
||||
iter->_file_iter = _file_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
void operator=(typename vfs::TDirectoryTree<WriteType>::IterImpl const& tree);
|
||||
tDirTree& _tree;
|
||||
typename tDirTree::tDirCatalogue::iterator _subdir_iter;
|
||||
typename tDirTree::tLocationType::Iterator _file_iter;
|
||||
};
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::IterImpl::IterImpl(vfs::TDirectoryTree<WriteType>& tree)
|
||||
: tBaseClass(), _tree(tree)
|
||||
{
|
||||
_subdir_iter = _tree.m_catDirs.begin();
|
||||
if(_subdir_iter != _tree.m_catDirs.end())
|
||||
{
|
||||
TSubDir<WriteType> *sdir = dynamic_cast<TSubDir<WriteType>*>(_subdir_iter->second);
|
||||
typename TSubDir<WriteType>::Iterator it = sdir->begin();
|
||||
_file_iter = it;
|
||||
if(_file_iter.end())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::IterImpl::~IterImpl()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::tFileType* vfs::TDirectoryTree<WriteType>::IterImpl::value()
|
||||
{
|
||||
if(!_file_iter.end())
|
||||
{
|
||||
return static_cast<typename vfs::TDirectoryTree<WriteType>::tFileType*>(_file_iter.value());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TDirectoryTree<WriteType>::IterImpl::next()
|
||||
{
|
||||
if(!_file_iter.end())
|
||||
{
|
||||
_file_iter.next();
|
||||
}
|
||||
// need to loop for the case when one or many sub directories are empty
|
||||
while(_file_iter.end())
|
||||
{
|
||||
if(_subdir_iter == _tree.m_catDirs.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_subdir_iter++;
|
||||
if(_subdir_iter != _tree.m_catDirs.end())
|
||||
{
|
||||
_file_iter = _subdir_iter->second->begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::TDirectoryTree(vfs::Path const& sMountPoint, vfs::Path const& sRealPath)
|
||||
: tBaseClass(sMountPoint,sRealPath)
|
||||
{};
|
||||
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::TDirectoryTree<WriteType>::~TDirectoryTree()
|
||||
{
|
||||
typename tDirCatalogue::iterator it = m_catDirs.begin();
|
||||
for(;it != m_catDirs.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
m_catDirs.clear();
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::init()
|
||||
{
|
||||
// contains local path
|
||||
typedef vfs::TSubDir<WriteType> tSubDir;
|
||||
typedef std::pair<vfs::Path,tSubDir*> tDirs;
|
||||
std::queue<tDirs> qSubDirs;
|
||||
qSubDirs.push(tDirs(vfs::Path(vfs::Const::EMPTY()),new tSubDir(this->m_mountPoint, this->m_realPath)));
|
||||
|
||||
m_catDirs[this->m_mountPoint] = qSubDirs.front().second;
|
||||
|
||||
vfs::String sFilename;
|
||||
tSubDir *pCurrentDir;
|
||||
vfs::Path oCurDir;
|
||||
while(!qSubDirs.empty())
|
||||
{
|
||||
pCurrentDir = qSubDirs.front().second;
|
||||
oCurDir = this->m_realPath;
|
||||
if( !qSubDirs.front().first.empty())
|
||||
{
|
||||
oCurDir += qSubDirs.front().first;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
vfs::OS::CIterateDirectory::EFileAttribute eFA;
|
||||
vfs::OS::CIterateDirectory iterFS(oCurDir, vfs::Const::STAR());
|
||||
while ( iterFS.nextFile(sFilename, eFA) )
|
||||
{
|
||||
if (StrCmp::Equal(vfs::Const::DOT(),sFilename) || StrCmp::Equal(vfs::Const::DOTDOT(),sFilename) || StrCmp::Equal(vfs::Const::DOTSVN(),sFilename) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (eFA == vfs::OS::CIterateDirectory::FA_DIRECTORY)
|
||||
{
|
||||
vfs::Path sLocal = qSubDirs.front().first + sFilename;
|
||||
|
||||
vfs::Path temp = this->m_mountPoint+sLocal;
|
||||
tSubDir *pNewDir = new tSubDir(sLocal, this->m_realPath+sLocal);
|
||||
qSubDirs.push(tDirs(sLocal,pNewDir));
|
||||
m_catDirs[temp] = pNewDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCurrentDir->addFile(vfs::Path(sFilename));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception &ex)
|
||||
{
|
||||
// probably directory doesn't exist. abort or continue???
|
||||
// -> abort AND continue
|
||||
VFS_LOG_WARNING(ex.what());
|
||||
return false;
|
||||
}
|
||||
qSubDirs.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::tFileType* vfs::TDirectoryTree<WriteType>::addFile(vfs::Path const& sFilename, bool bDeleteOldFile)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
sFilename.splitLast(sDir,sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
vfs::Path sTemp,sCreateDir,sLeft,sRight = sDir;
|
||||
while(!sRight.empty())
|
||||
{
|
||||
sRight.splitFirst(sLeft,sTemp);
|
||||
sRight = sTemp;
|
||||
sCreateDir += sLeft;
|
||||
if(!this->createSubDirectory(sCreateDir))
|
||||
{
|
||||
VFS_THROW(_BS(L"could not create directory : ") << sCreateDir << _BS::wget);
|
||||
}
|
||||
}
|
||||
it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->addFile(sFile,bDeleteOldFile);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::addFile(tFileType* pFile, bool bDeleteOldFile)
|
||||
{
|
||||
// no files from outside
|
||||
// these files are not connected with the correct directory object
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::deleteDirectory(vfs::Path const& sDirPath)
|
||||
{
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDirPath);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
// no such directory
|
||||
return false;
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->deleteDirectory(sDirPath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::deleteFileFromDirectory(vfs::Path const& sFileName)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
sFileName.splitLast(sDir,sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
// no such directory
|
||||
return false;
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->deleteFileFromDirectory(sFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* IVFSLocation interface
|
||||
*/
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::fileExists(vfs::Path const& sFileName)
|
||||
{
|
||||
vfs::Path sDir, sFile;
|
||||
sFileName.splitLast(sDir, sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
// no such directory
|
||||
return false;
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->fileExists(sFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
vfs::IBaseFile* vfs::TDirectoryTree<WriteType>::getFile(vfs::Path const& sFileName)
|
||||
{
|
||||
return getFileTyped(sFileName);
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::tFileType* vfs::TDirectoryTree<WriteType>::getFileTyped(vfs::Path const& sFileName)
|
||||
{
|
||||
vfs::Path sDir, sFile;
|
||||
sFileName.splitLast(sDir, sFile);
|
||||
typename tDirCatalogue::iterator it = m_catDirs.find(sDir);
|
||||
if(it == m_catDirs.end())
|
||||
{
|
||||
// no such directory
|
||||
return NULL;
|
||||
}
|
||||
if(it->second)
|
||||
{
|
||||
return it->second->getFileTyped(sFile);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
bool vfs::TDirectoryTree<WriteType>::createSubDirectory(vfs::Path const& sSubDirPath)
|
||||
{
|
||||
if(vfs::OS::createRealDirectory( this->m_realPath + sSubDirPath ))
|
||||
{
|
||||
if( m_catDirs[sSubDirPath] == NULL)
|
||||
{
|
||||
m_catDirs[sSubDirPath] = new vfs::TSubDir<WriteType>(sSubDirPath, this->m_realPath + sSubDirPath);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
void vfs::TDirectoryTree<WriteType>::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
typename tDirCatalogue::iterator it = m_catDirs.begin();
|
||||
for(;it != m_catDirs.end(); ++it)
|
||||
{
|
||||
rlSubDirs.push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WriteType>
|
||||
typename vfs::TDirectoryTree<WriteType>::Iterator vfs::TDirectoryTree<WriteType>::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(*this));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
template class vfs::TDirectoryTree<vfs::IWritable>; // explicit template class instantiation
|
||||
template class vfs::TDirectoryTree<vfs::IWriteType>; // explicit template class instantiation
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Location/vfs_lib_dir.cpp
|
||||
* - class for readonly (sub)directories in archives/libraries
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Location/vfs_lib_dir.h>
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
|
||||
class vfs::CLibDirectory::IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
public:
|
||||
IterImpl(CLibDirectory& lib);
|
||||
virtual ~IterImpl();
|
||||
virtual vfs::CLibDirectory::tFileType* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone();
|
||||
private:
|
||||
void operator=(vfs::CLibDirectory::IterImpl const& iter);
|
||||
|
||||
vfs::CLibDirectory& _lib;
|
||||
vfs::CLibDirectory::tFileCatalogue::iterator _iter;
|
||||
};
|
||||
|
||||
vfs::CLibDirectory::IterImpl::IterImpl(CLibDirectory& lib)
|
||||
: tBaseClass(), _lib(lib)
|
||||
{
|
||||
_iter = _lib.m_files.begin();
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::IterImpl::~IterImpl()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::IterImpl::value()
|
||||
{
|
||||
if(_iter != _lib.m_files.end())
|
||||
{
|
||||
return _iter->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfs::CLibDirectory::IterImpl::next()
|
||||
{
|
||||
if(_iter != _lib.m_files.end())
|
||||
{
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::IterImpl::tBaseClass* vfs::CLibDirectory::IterImpl::clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl(_lib);
|
||||
iter->_iter = _iter;
|
||||
return iter;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
vfs::CLibDirectory::CLibDirectory(vfs::Path const& sLocalPath, vfs::Path const& sRealPath)
|
||||
: tBaseClass(sLocalPath,sRealPath)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::~CLibDirectory()
|
||||
{
|
||||
tFileCatalogue::iterator it = m_files.begin();
|
||||
for(; it != m_files.end(); ++it)
|
||||
{
|
||||
// don't delete objects here
|
||||
//delete it->second;
|
||||
}
|
||||
m_files.clear();
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::addFile(vfs::Path const& filename, bool deleteOldFile)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::addFile(tFileType* file, bool deleteOldFile)
|
||||
{
|
||||
if(!file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vfs::Path const& name = file->getName();
|
||||
tFileType* oldFile = m_files[name];
|
||||
if(oldFile && (oldFile != file) )
|
||||
{
|
||||
if(deleteOldFile)
|
||||
{
|
||||
delete oldFile;
|
||||
m_files[name] = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_files[name] = file;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::deleteDirectory(vfs::Path const& dirPath)
|
||||
{
|
||||
//if( !(m_mountPoint == dirPath) )
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
//if(implementsWritable())
|
||||
//{
|
||||
// tFileCatalogue::iterator it = m_files.begin();
|
||||
// for(; it != m_files.end(); ++it)
|
||||
// {
|
||||
// //delete it->second;
|
||||
// }
|
||||
// m_files.clear();
|
||||
// return true;
|
||||
//}
|
||||
VFS_LOG_ERROR(L"called 'deleteDirectory', 'vfs::CLibDirectory' doesn't implement the IWritable interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::deleteFileFromDirectory(vfs::Path const& filename)
|
||||
{
|
||||
//if(implementsWritable())
|
||||
//{
|
||||
// tFileCatalogue::iterator it = m_files.find(filename);
|
||||
// if(it != m_files.end())
|
||||
// {
|
||||
// delete it->second;
|
||||
// m_files.erase(it);
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
VFS_LOG_ERROR(L"called 'deleteFileFromDirectory', 'vfs::CLibDirectory' doesn't implement the IWritable interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::fileExists(vfs::Path const& filename)
|
||||
{
|
||||
return (m_files[filename] != NULL);
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CLibDirectory::getFile(vfs::Path const& filename)
|
||||
{
|
||||
return getFileTyped(filename);
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::tFileType* vfs::CLibDirectory::getFileTyped(vfs::Path const& filename)
|
||||
{
|
||||
tFileCatalogue::iterator it = m_files.find(filename);
|
||||
if(it != m_files.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CLibDirectory::createSubDirectory(vfs::Path const& subDirPath)
|
||||
{
|
||||
// libraries are readonly
|
||||
return false;
|
||||
}
|
||||
|
||||
void vfs::CLibDirectory::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
vfs::CLibDirectory::Iterator vfs::CLibDirectory::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(*this));
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/Location/vfs_uncompressed_lib_base.cpp
|
||||
* - partially implements library interface for uncompressed archive files
|
||||
* - initialization is done in format-specific sub-classes
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/Location/vfs_uncompressed_lib_base.h>
|
||||
|
||||
/********************************************************************************************/
|
||||
vfs::CUncompressedLibraryBase::SFileData& vfs::CUncompressedLibraryBase::_fileDataFromHandle(tFileType* handle)
|
||||
{
|
||||
tFileData::iterator it = m_fileData.find(handle);
|
||||
if(it != m_fileData.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
VFS_THROW(L"Invalid file handle");
|
||||
}
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
class vfs::CUncompressedLibraryBase::IterImpl : public vfs::IBaseLocation::Iterator::IImplementation
|
||||
{
|
||||
typedef vfs::IBaseLocation::Iterator::IImplementation tBaseClass;
|
||||
public:
|
||||
IterImpl(CUncompressedLibraryBase& lib);
|
||||
virtual ~IterImpl();
|
||||
virtual tFileType* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl(*_lib);
|
||||
iter->_iter = _iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
vfs::CUncompressedLibraryBase* _lib;
|
||||
vfs::CUncompressedLibraryBase::tFileData::iterator _iter;
|
||||
};
|
||||
|
||||
|
||||
vfs::CUncompressedLibraryBase::IterImpl::IterImpl(vfs::CUncompressedLibraryBase &lib)
|
||||
: tBaseClass(), _lib(&lib)
|
||||
{
|
||||
_iter = _lib->m_fileData.begin();
|
||||
}
|
||||
vfs::CUncompressedLibraryBase::IterImpl::~IterImpl()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::tFileType* vfs::CUncompressedLibraryBase::IterImpl::value()
|
||||
{
|
||||
if(_iter != _lib->m_fileData.end())
|
||||
{
|
||||
return _iter->first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::IterImpl::next()
|
||||
{
|
||||
if(_iter != _lib->m_fileData.end())
|
||||
{
|
||||
_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
vfs::CUncompressedLibraryBase::CUncompressedLibraryBase(vfs::tReadableFile *libraryFile, vfs::Path const& mountPoint, bool ownFile)
|
||||
: vfs::ILibrary(libraryFile,mountPoint,ownFile), m_numberOfOpenedFiles(0)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::~CUncompressedLibraryBase()
|
||||
{
|
||||
this->closeLibrary();
|
||||
// delete sub dirs from catalogue
|
||||
tDirCatalogue::iterator it = m_dirs.begin();
|
||||
for(; it != m_dirs.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
// LibData is invalid
|
||||
// just clear it, since the file handles were deleted before
|
||||
m_fileData.clear();
|
||||
m_dirs.clear();
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::closeLibrary()
|
||||
{
|
||||
tFileData::iterator it = m_fileData.begin();
|
||||
for(; it != m_fileData .end(); ++it)
|
||||
{
|
||||
// what if closing of (at least) one file fails?? continue or not??
|
||||
// in the end, these are not real files!
|
||||
VFS_IGNOREEXCEPTION(it->first->close(), true);
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::CUncompressedLibraryBase::fileExists(vfs::Path const& filename)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
filename.splitLast(sDir,sFile);
|
||||
tDirCatalogue::iterator it = m_dirs.find(sDir);
|
||||
if(it != m_dirs.end())
|
||||
{
|
||||
return it->second->fileExists(sFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CUncompressedLibraryBase::getFile(vfs::Path const& filename)
|
||||
{
|
||||
return getFileTyped(filename);
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::tFileType* vfs::CUncompressedLibraryBase::getFileTyped(vfs::Path const& filename)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
filename.splitLast(sDir,sFile);
|
||||
tDirCatalogue::iterator it = m_dirs.find(sDir);
|
||||
if(it != m_dirs.end())
|
||||
{
|
||||
return it->second->getFileTyped(sFile);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::close(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
|
||||
// reset read position
|
||||
// can't do this when opening file,
|
||||
// because you could try to open a file when it is already open and would so reset the read position
|
||||
file._currentReadPosition = 0;
|
||||
if(m_numberOfOpenedFiles > 0)
|
||||
{
|
||||
m_numberOfOpenedFiles--;
|
||||
if(m_numberOfOpenedFiles == 0)
|
||||
{
|
||||
m_libraryFile->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
bool vfs::CUncompressedLibraryBase::openRead(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fileDataFromHandle(fileHandle);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
|
||||
m_numberOfOpenedFiles++;
|
||||
if(m_numberOfOpenedFiles == 1)
|
||||
{
|
||||
if(!m_libraryFile->isOpenRead() && !m_libraryFile->openRead())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// already open
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CUncompressedLibraryBase::read(tFileType *fileHandle, vfs::Byte* data, vfs::size_t bytesToRead)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
|
||||
if( (file._currentReadPosition + bytesToRead) > file._fileSize )
|
||||
{
|
||||
bytesToRead = file._fileSize - file._currentReadPosition;
|
||||
}
|
||||
if(bytesToRead == 0)
|
||||
{
|
||||
// eof
|
||||
return 0;
|
||||
}
|
||||
// set lib-file's read-location to match location of lib-file
|
||||
m_libraryFile->setReadPosition(file._fileOffset + file._currentReadPosition, IBaseFile::SD_BEGIN);
|
||||
|
||||
vfs::size_t bytesRead = m_libraryFile->read(data, bytesToRead);
|
||||
VFS_THROW_IFF( bytesToRead == bytesRead, L"Number of bytes doesn't match" );
|
||||
file._currentReadPosition += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CUncompressedLibraryBase::getReadPosition(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _fileDataFromHandle(fileHandle)._currentReadPosition;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::setReadPosition(tFileType *fileHandle, vfs::size_t positionInBytes)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
if( positionInBytes > file._fileSize )
|
||||
{
|
||||
positionInBytes = file._fileSize;
|
||||
}
|
||||
|
||||
// positionInBytes is offset to file-offset
|
||||
file._currentReadPosition = positionInBytes;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
static inline vfs::offset_t clampReadPosition(vfs::offset_t const& off, vfs::size_t const& size)
|
||||
{
|
||||
return ( off < 0 ) ? ( 0 ) : ( (vfs::size_t)off > size ? size : off );
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::setReadPosition(tFileType *fileHandle, vfs::offset_t offsetInBytes, IBaseFile::ESeekDir seekDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
SFileData& file = _fileDataFromHandle(fileHandle);
|
||||
|
||||
if(seekDir == IBaseFile::SD_BEGIN)
|
||||
{
|
||||
file._currentReadPosition = clampReadPosition(offsetInBytes, file._fileSize);
|
||||
}
|
||||
else if(seekDir == IBaseFile::SD_CURRENT)
|
||||
{
|
||||
vfs::offset_t pos = file._currentReadPosition + offsetInBytes;
|
||||
file._currentReadPosition = clampReadPosition(pos, file._fileSize);
|
||||
}
|
||||
else if(seekDir == IBaseFile::SD_END)
|
||||
{
|
||||
vfs::offset_t pos = file._currentReadPosition + offsetInBytes;
|
||||
file._currentReadPosition = clampReadPosition(pos, file._fileSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(L"Unknown seek direction");
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CUncompressedLibraryBase::getSize(tFileType *fileHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _fileDataFromHandle(fileHandle)._fileSize;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::CUncompressedLibraryBase::getSubDirList(std::list<vfs::Path>& rlSubDirs)
|
||||
{
|
||||
tDirCatalogue::iterator it = m_dirs.begin();
|
||||
for(;it != m_dirs.end(); ++it)
|
||||
{
|
||||
rlSubDirs.push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
vfs::CUncompressedLibraryBase::Iterator vfs::CUncompressedLibraryBase::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(*this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
## Core
|
||||
|
||||
##
|
||||
set(INCLUDE_Core_root
|
||||
${MOD_INCLUDE}/vfs.h
|
||||
${MOD_INCLUDE}/vfs_debug.h
|
||||
${MOD_INCLUDE}/vfs_file_raii.h
|
||||
${MOD_INCLUDE}/vfs_init.h
|
||||
${MOD_INCLUDE}/vfs_os_functions.h
|
||||
${MOD_INCLUDE}/vfs_path.h
|
||||
${MOD_INCLUDE}/vfs_profile.h
|
||||
${MOD_INCLUDE}/vfs_string.h
|
||||
${MOD_INCLUDE}/vfs_types.h
|
||||
${MOD_INCLUDE}/vfs_vfile.h
|
||||
${MOD_INCLUDE}/vfs_vloc.h
|
||||
)
|
||||
set(SOURCE_Core_root
|
||||
${MOD_SOURCE}/vfs.cpp
|
||||
${MOD_SOURCE}/vfs_debug.cpp
|
||||
${MOD_SOURCE}/vfs_file_raii.cpp
|
||||
${MOD_SOURCE}/vfs_init.cpp
|
||||
${MOD_SOURCE}/vfs_os_functions.cpp
|
||||
${MOD_SOURCE}/vfs_path.cpp
|
||||
${MOD_SOURCE}/vfs_profile.cpp
|
||||
${MOD_SOURCE}/vfs_string.cpp
|
||||
${MOD_SOURCE}/vfs_types.cpp
|
||||
${MOD_SOURCE}/vfs_vfile.cpp
|
||||
${MOD_SOURCE}/vfs_vloc.cpp
|
||||
)
|
||||
source_group("Core" FILES ${INCLUDE_Core_root} ${SOURCE_Core_root})
|
||||
|
||||
##
|
||||
set(INCLUDE_Core_File
|
||||
${MOD_INCLUDE}/File/vfs_buffer_file.h
|
||||
${MOD_INCLUDE}/File/vfs_dir_file.h
|
||||
${MOD_INCLUDE}/File/vfs_file.h
|
||||
${MOD_INCLUDE}/File/vfs_lib_file.h
|
||||
)
|
||||
set(SOURCE_Core_File
|
||||
${MOD_SOURCE}/File/vfs_buffer_file.cpp
|
||||
${MOD_SOURCE}/File/vfs_dir_file.cpp
|
||||
${MOD_SOURCE}/File/vfs_file.cpp
|
||||
${MOD_SOURCE}/File/vfs_lib_file.cpp
|
||||
)
|
||||
source_group("Core\\File" FILES ${INCLUDE_Core_File} ${SOURCE_Core_File})
|
||||
|
||||
##
|
||||
set(INCLUDE_Core_Interface
|
||||
${MOD_INCLUDE}/Interface/vfs_directory_interface.h
|
||||
${MOD_INCLUDE}/Interface/vfs_file_interface.h
|
||||
${MOD_INCLUDE}/Interface/vfs_iterator_interface.h
|
||||
${MOD_INCLUDE}/Interface/vfs_library_interface.h
|
||||
${MOD_INCLUDE}/Interface/vfs_location_interface.h
|
||||
)
|
||||
set(SOURCE_Core_Interface
|
||||
${MOD_SOURCE}/Interface/vfs_interface_members.cpp
|
||||
)
|
||||
source_group("Core\\Interface" FILES ${INCLUDE_Core_Interface} ${SOURCE_Core_Interface})
|
||||
|
||||
##
|
||||
set(INCLUDE_Core_Location
|
||||
${MOD_INCLUDE}/Location/vfs_directory_tree.h
|
||||
${MOD_INCLUDE}/Location/vfs_lib_dir.h
|
||||
${MOD_INCLUDE}/Location/vfs_uncompressed_lib_base.h
|
||||
)
|
||||
set(SOURCE_Core_Location
|
||||
${MOD_SOURCE}/Location/vfs_directory_tree.cpp
|
||||
${MOD_SOURCE}/Location/vfs_lib_dir.cpp
|
||||
${MOD_SOURCE}/Location/vfs_uncompressed_lib_base.cpp
|
||||
)
|
||||
source_group("Core\\Location" FILES ${INCLUDE_Core_Location} ${SOURCE_Core_Location})
|
||||
|
||||
set(${mod}_files
|
||||
${INCLUDE_Core_root} ${SOURCE_Core_root}
|
||||
${INCLUDE_Core_File} ${SOURCE_Core_File}
|
||||
${INCLUDE_Core_Interface} ${SOURCE_Core_Interface}
|
||||
${INCLUDE_Core_Location} ${SOURCE_Core_Location}
|
||||
CACHE INTERNAL ""
|
||||
)
|
||||
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs.cpp
|
||||
* - primary interface for the using program, get files from the VFS internal storage
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_types.h>
|
||||
#include <vfs/Core/vfs.h>
|
||||
|
||||
#include <vfs/Core/Interface/vfs_directory_interface.h>
|
||||
#include <vfs/Core/Interface/vfs_file_interface.h>
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <vfs/Core/File/vfs_dir_file.h>
|
||||
#include <vfs/Core/File/vfs_lib_file.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
#include <vfs/Core/vfs_vfile.h>
|
||||
|
||||
#include <vfs/Tools/vfs_property_container.h>
|
||||
#include <vfs/Tools/vfs_parser_tools.h>
|
||||
|
||||
#include <stack>
|
||||
|
||||
template class vfs::TIterator<vfs::tReadableFile>; // explicit instantiation
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
class vfs::CVirtualFileSystem::CRegularIterator : public vfs::CVirtualFileSystem::Iterator::IImplementation
|
||||
{
|
||||
friend class vfs::CVirtualFileSystem;
|
||||
typedef vfs::CVirtualFileSystem::Iterator::IImplementation tBaseClass;
|
||||
|
||||
CRegularIterator(vfs::CVirtualFileSystem* pVFS);
|
||||
public:
|
||||
CRegularIterator() : tBaseClass(), m_VFS(NULL)
|
||||
{};
|
||||
virtual ~CRegularIterator()
|
||||
{};
|
||||
|
||||
virtual vfs::tReadableFile* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
CRegularIterator* iter = new CRegularIterator();
|
||||
iter->m_VFS = m_VFS;
|
||||
iter->_vloc_iter = _vloc_iter;
|
||||
iter->_vfile_iter = _vfile_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
vfs::CVirtualFileSystem* m_VFS;
|
||||
vfs::CVirtualFileSystem::tVFS::iterator _vloc_iter;
|
||||
vfs::CVirtualLocation::Iterator _vfile_iter;
|
||||
};
|
||||
|
||||
vfs::CVirtualFileSystem::CRegularIterator::CRegularIterator(vfs::CVirtualFileSystem* pVFS)
|
||||
: tBaseClass(), m_VFS(pVFS)
|
||||
{
|
||||
_vloc_iter = m_VFS->m_mapFS.begin();
|
||||
if(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
_vfile_iter = _vloc_iter->second->iterate();
|
||||
}
|
||||
}
|
||||
|
||||
vfs::tReadableFile* vfs::CVirtualFileSystem::CRegularIterator::value()
|
||||
{
|
||||
bool bExclusiveVLoc = false;
|
||||
if(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
bExclusiveVLoc = _vloc_iter->second->getIsExclusive();
|
||||
}
|
||||
if(!_vfile_iter.end())
|
||||
{
|
||||
vfs::CVirtualFile* pVFile = _vfile_iter.value();
|
||||
if(pVFile)
|
||||
{
|
||||
if(bExclusiveVLoc)
|
||||
{
|
||||
return vfs::tReadableFile::cast(pVFile->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE));
|
||||
}
|
||||
else
|
||||
{
|
||||
return vfs::tReadableFile::cast(pVFile->file(vfs::CVirtualFile::SF_TOP));
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void vfs::CVirtualFileSystem::CRegularIterator::next()
|
||||
{
|
||||
if(!_vfile_iter.end())
|
||||
{
|
||||
_vfile_iter.next();
|
||||
}
|
||||
while(_vfile_iter.end())
|
||||
{
|
||||
if(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
_vloc_iter++;
|
||||
if(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
_vfile_iter = _vloc_iter->second->iterate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
class vfs::CVirtualFileSystem::CMatchingIterator : public vfs::CVirtualFileSystem::Iterator::IImplementation
|
||||
{
|
||||
friend class vfs::CVirtualFileSystem;
|
||||
typedef vfs::CVirtualFileSystem::Iterator::IImplementation tBaseClass;
|
||||
|
||||
CMatchingIterator(vfs::Path const& sPattern, vfs::CVirtualFileSystem* pVFS);
|
||||
public:
|
||||
CMatchingIterator() : tBaseClass(), m_VFS(NULL)
|
||||
{};
|
||||
virtual ~CMatchingIterator()
|
||||
{};
|
||||
|
||||
virtual vfs::tReadableFile* value();
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
CMatchingIterator* iter = new CMatchingIterator();
|
||||
iter->m_sLocPattern = m_sLocPattern;
|
||||
iter->m_sFilePattern = m_sFilePattern;
|
||||
iter->m_VFS = m_VFS;
|
||||
iter->_vloc_iter = _vloc_iter;
|
||||
iter->_vfile_iter = _vfile_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
bool nextLocationMatch();
|
||||
bool nextFileMatch();
|
||||
private:
|
||||
vfs::Path m_sLocPattern, m_sFilePattern;
|
||||
vfs::CVirtualFileSystem* m_VFS;
|
||||
vfs::CVirtualFileSystem::tVFS::iterator _vloc_iter;
|
||||
vfs::CVirtualLocation::Iterator _vfile_iter;
|
||||
};
|
||||
|
||||
vfs::CVirtualFileSystem::CMatchingIterator::CMatchingIterator(vfs::Path const& sPattern, vfs::CVirtualFileSystem* pVFS)
|
||||
: tBaseClass(), m_VFS(pVFS)
|
||||
{
|
||||
if(sPattern() == vfs::Const::STAR())
|
||||
{
|
||||
m_sLocPattern = vfs::Path(vfs::Const::STAR());
|
||||
m_sFilePattern = vfs::Path(vfs::Const::STAR());
|
||||
}
|
||||
else
|
||||
{
|
||||
sPattern.splitLast(m_sLocPattern,m_sFilePattern);
|
||||
}
|
||||
|
||||
_vloc_iter = m_VFS->m_mapFS.begin();
|
||||
while(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
if( matchPattern(m_sLocPattern(),_vloc_iter->second->cPath()) )
|
||||
{
|
||||
bool bExclusiveVLoc = _vloc_iter->second->getIsExclusive();
|
||||
_vfile_iter = _vloc_iter->second->iterate();
|
||||
while(!_vfile_iter.end())
|
||||
{
|
||||
vfs::IBaseFile* pFile = NULL;
|
||||
if(bExclusiveVLoc)
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_TOP);
|
||||
}
|
||||
if(pFile)
|
||||
{
|
||||
vfs::Path const& filename = pFile->getName();
|
||||
if( matchPattern(m_sFilePattern(),filename()) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
_vfile_iter.next();
|
||||
}
|
||||
}
|
||||
_vloc_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::tReadableFile* vfs::CVirtualFileSystem::CMatchingIterator::value()
|
||||
{
|
||||
bool bExclusiveVLoc = false;
|
||||
if( _vloc_iter != m_VFS->m_mapFS.end() )
|
||||
{
|
||||
bExclusiveVLoc = _vloc_iter->second->getIsExclusive();
|
||||
}
|
||||
if(!_vfile_iter.end())
|
||||
{
|
||||
vfs::CVirtualFile* pVFile = _vfile_iter.value();
|
||||
if(pVFile)
|
||||
{
|
||||
vfs::IBaseFile* pFile = NULL;
|
||||
if(bExclusiveVLoc)
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_TOP);
|
||||
}
|
||||
return vfs::tReadableFile::cast(pFile);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::CMatchingIterator::nextLocationMatch()
|
||||
{
|
||||
while(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
_vloc_iter++;
|
||||
if(_vloc_iter != m_VFS->m_mapFS.end())
|
||||
{
|
||||
if(matchPattern(m_sLocPattern(),_vloc_iter->second->cPath()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool vfs::CVirtualFileSystem::CMatchingIterator::nextFileMatch()
|
||||
{
|
||||
bool bExclusiveVLoc = false;
|
||||
if( _vloc_iter != m_VFS->m_mapFS.end() )
|
||||
{
|
||||
bExclusiveVLoc = _vloc_iter->second->getIsExclusive();
|
||||
}
|
||||
while(!_vfile_iter.end())
|
||||
{
|
||||
_vfile_iter.next();
|
||||
if(!_vfile_iter.end())
|
||||
{
|
||||
vfs::IBaseFile* pFile = NULL;
|
||||
if(bExclusiveVLoc)
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_TOP);
|
||||
}
|
||||
if(pFile)
|
||||
{
|
||||
vfs::Path const& filename = pFile->getName();
|
||||
if(matchPattern(m_sFilePattern(),filename()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void vfs::CVirtualFileSystem::CMatchingIterator::next()
|
||||
{
|
||||
if(nextFileMatch())
|
||||
{
|
||||
return;
|
||||
}
|
||||
while(nextLocationMatch())
|
||||
{
|
||||
_vfile_iter = _vloc_iter->second->iterate();
|
||||
if(!_vfile_iter.end())
|
||||
{
|
||||
bool bExclusiveVLoc = _vloc_iter->second->getIsExclusive();
|
||||
vfs::IBaseFile* pFile = NULL;
|
||||
if(bExclusiveVLoc)
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFile = _vfile_iter.value()->file(vfs::CVirtualFile::SF_TOP);
|
||||
}
|
||||
if(pFile && matchPattern(m_sFilePattern(),pFile->getName()()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(nextFileMatch())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
bool vfs::canWrite()
|
||||
{
|
||||
vfs::CVirtualProfile *prof = getVFS()->getProfileStack()->topProfile();
|
||||
return prof && prof->cWritable;
|
||||
}
|
||||
|
||||
vfs::CVirtualFileSystem* getVFS()
|
||||
{
|
||||
return vfs::CVirtualFileSystem::getVFS();
|
||||
}
|
||||
|
||||
vfs::CVirtualFileSystem* vfs::CVirtualFileSystem::m_pSingleton = NULL;
|
||||
|
||||
vfs::CVirtualFileSystem* vfs::CVirtualFileSystem::getVFS()
|
||||
{
|
||||
if(!m_pSingleton)
|
||||
{
|
||||
m_pSingleton = new CVirtualFileSystem();
|
||||
}
|
||||
return m_pSingleton;
|
||||
}
|
||||
|
||||
void vfs::CVirtualFileSystem::shutdownVFS()
|
||||
{
|
||||
if(m_pSingleton)
|
||||
{
|
||||
delete m_pSingleton;
|
||||
m_pSingleton = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vfs::CVirtualFileSystem::CVirtualFileSystem()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CVirtualFileSystem::~CVirtualFileSystem()
|
||||
{
|
||||
tVFS::iterator it = m_mapFS.begin();
|
||||
for(; it != m_mapFS.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
m_mapFS.clear();
|
||||
}
|
||||
|
||||
vfs::CProfileStack* vfs::CVirtualFileSystem::getProfileStack()
|
||||
{
|
||||
return &m_oProfileStack;
|
||||
}
|
||||
|
||||
vfs::CVirtualFileSystem::Iterator vfs::CVirtualFileSystem::begin()
|
||||
{
|
||||
return Iterator(new vfs::CVirtualFileSystem::CRegularIterator(this));
|
||||
}
|
||||
|
||||
vfs::CVirtualFileSystem::Iterator vfs::CVirtualFileSystem::begin(vfs::Path const& sPattern)
|
||||
{
|
||||
return Iterator(new vfs::CVirtualFileSystem::CMatchingIterator(sPattern,this));
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::addLocation(vfs::IBaseLocation* pLocation, vfs::CVirtualProfile *pProfile)
|
||||
{
|
||||
VFS_THROW_IFF(pLocation != NULL, L"Invalid location object");
|
||||
VFS_THROW_IFF(pProfile!= NULL, L"Invalid location object");
|
||||
|
||||
std::list<vfs::Path> lSubDirs;
|
||||
pLocation->getSubDirList(lSubDirs);
|
||||
std::list<vfs::Path>::const_iterator sd_cit = lSubDirs.begin();
|
||||
for(;sd_cit != lSubDirs.end(); ++sd_cit)
|
||||
{
|
||||
this->getVirtualLocation(*sd_cit, true);
|
||||
}
|
||||
|
||||
vfs::IBaseLocation::Iterator it = pLocation->begin();
|
||||
for(; !it.end(); it.next())
|
||||
{
|
||||
vfs::IBaseFile *pFile = it.value();
|
||||
vfs::Path const& sPath = pFile->getPath();
|
||||
vfs::Path dir,file;
|
||||
sPath.splitLast(dir,file);
|
||||
|
||||
CVirtualLocation* pLoc = this->getVirtualLocation(dir,true);
|
||||
pLoc->addFile(pFile, pProfile->cName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs::tReadableFile* vfs::CVirtualFileSystem::getReadFile(vfs::Path const& rLocalFilePath, vfs::CVirtualFile::ESearchFile eSF)
|
||||
{
|
||||
return vfs::tReadableFile::cast(this->getFile(rLocalFilePath,eSF));
|
||||
}
|
||||
|
||||
vfs::tWritableFile* vfs::CVirtualFileSystem::getWriteFile(vfs::Path const& rLocalFilePath, vfs::CVirtualFile::ESearchFile eSF)
|
||||
{
|
||||
return vfs::tWritableFile::cast(this->getFile(rLocalFilePath,eSF));
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CVirtualFileSystem::getFile(vfs::Path const& rLocalFilePath, vfs::CVirtualFile::ESearchFile eSF)
|
||||
{
|
||||
VFS_LOG_DEBUG( (L"Get file : " + rLocalFilePath()).c_str() );
|
||||
vfs::Path sDir,sFile;
|
||||
rLocalFilePath.splitLast(sDir,sFile);
|
||||
|
||||
vfs::CVirtualLocation* pVLoc = this->getVirtualLocation(sDir);
|
||||
if(pVLoc)
|
||||
{
|
||||
vfs::CVirtualFile *pVFile = pVLoc->getVirtualFile(sFile);
|
||||
if(pVFile)
|
||||
{
|
||||
if(pVLoc->getIsExclusive())
|
||||
{
|
||||
return pVFile->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
|
||||
}
|
||||
return pVFile->file(eSF);
|
||||
}
|
||||
}
|
||||
VFS_LOG_DEBUG( _BS(L"Could not find file : ") << rLocalFilePath << _BS::wget );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs::tReadableFile* vfs::CVirtualFileSystem::getReadFile(vfs::Path const& rLocalFilePath, vfs::String const& sProfileName)
|
||||
{
|
||||
return vfs::tReadableFile::cast(this->getFile(rLocalFilePath, sProfileName));
|
||||
}
|
||||
|
||||
vfs::tWritableFile* vfs::CVirtualFileSystem::getWriteFile(vfs::Path const& rLocalFilePath, vfs::String const& sProfileName)
|
||||
{
|
||||
return vfs::tWritableFile::cast(this->getFile(rLocalFilePath, sProfileName));
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CVirtualFileSystem::getFile(vfs::Path const& rLocalFilePath, vfs::String const& sProfileName)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
rLocalFilePath.splitLast(sDir,sFile);
|
||||
|
||||
tVFS::iterator it_loc = m_mapFS.find(sDir);
|
||||
if(it_loc == m_mapFS.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
vfs::CVirtualLocation* pVLoc = it_loc->second;
|
||||
if(pVLoc)
|
||||
{
|
||||
return pVLoc->getFile(sFile,sProfileName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::fileExists(vfs::Path const& rLocalFilePath, std::string const& sProfileName)
|
||||
{
|
||||
return this->getFile(rLocalFilePath, sProfileName) != NULL;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::fileExists(vfs::Path const& rLocalFilePath, vfs::CVirtualFile::ESearchFile eSF)
|
||||
{
|
||||
return this->getFile(rLocalFilePath, eSF) != NULL;
|
||||
}
|
||||
|
||||
vfs::CVirtualLocation* vfs::CVirtualFileSystem::getVirtualLocation(vfs::Path const& sPath, bool bCreate)
|
||||
{
|
||||
tVFS::iterator it = m_mapFS.find(sPath);
|
||||
if(it == m_mapFS.end())
|
||||
{
|
||||
if(bCreate)
|
||||
{
|
||||
vfs::CVirtualLocation* pVLoc = new vfs::CVirtualLocation(sPath);
|
||||
m_mapFS.insert(std::make_pair(sPath,pVLoc));
|
||||
return pVLoc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::removeDirectoryFromFS(vfs::Path const& sDir)
|
||||
{
|
||||
vfs::Path pattern = sDir + "*";
|
||||
std::list<vfs::Path> files;
|
||||
|
||||
Iterator it = this->begin(pattern);
|
||||
for(; !it.end(); it.next())
|
||||
{
|
||||
if(it.value()->implementsWritable())
|
||||
{
|
||||
files.push_back(it.value()->getPath());
|
||||
}
|
||||
}
|
||||
bool success = true;
|
||||
std::list<vfs::Path>::iterator fit = files.begin();
|
||||
for(; fit != files.end(); ++fit)
|
||||
{
|
||||
success &= this->removeFileFromFS(*fit);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::removeFileFromFS(vfs::Path const& sFilePath)
|
||||
{
|
||||
vfs::Path sPath,sFile;
|
||||
sFilePath.splitLast(sPath,sFile);
|
||||
vfs::CVirtualProfile *pProf = m_oProfileStack.getWriteProfile();
|
||||
if(pProf)
|
||||
{
|
||||
vfs::IBaseLocation *pBL = pProf->getLocation(sPath);
|
||||
if(pBL && pBL->implementsWritable())
|
||||
{
|
||||
vfs::TDirectory<vfs::IWritable> *pDir = dynamic_cast<vfs::TDirectory<vfs::IWritable>*>(pBL);
|
||||
if(pDir)
|
||||
{
|
||||
bool bSuccess = false;
|
||||
// remove file from virtual structures first
|
||||
vfs::IBaseFile* file = pDir->getFile(sFilePath);
|
||||
if(file)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
sFilePath.splitLast(sDir,sFile);
|
||||
vfs::CVirtualLocation *pVLoc = this->getVirtualLocation(sDir);
|
||||
if(pVLoc)
|
||||
{
|
||||
bSuccess = pVLoc->removeFile(file);
|
||||
}
|
||||
}
|
||||
// delete actual file
|
||||
return bSuccess && pDir->deleteFileFromDirectory(sFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualFileSystem::createNewFile(vfs::Path const& sFilename)
|
||||
{
|
||||
vfs::Path sPath,sFile;
|
||||
sFilename.splitLast(sPath,sFile);
|
||||
vfs::CVirtualProfile *pProf = m_oProfileStack.getWriteProfile();
|
||||
if(pProf)
|
||||
{
|
||||
bool bIsExclusive = false;
|
||||
bool bNewLocation = false;
|
||||
vfs::IBaseLocation *pProfLoc = pProf->getLocation(sPath);
|
||||
if(!pProfLoc)
|
||||
{
|
||||
// try to find closest match
|
||||
vfs::Path sTemp, sCreateDir, sRight, sLeft = sPath;
|
||||
while(!pProfLoc && !sLeft.empty())
|
||||
{
|
||||
sLeft.splitLast(sTemp,sRight);
|
||||
sLeft = sTemp;
|
||||
sCreateDir = sRight + sCreateDir;
|
||||
pProfLoc = pProf->getLocation(sLeft);
|
||||
}
|
||||
// see if the closest match is exclusive
|
||||
// if yes, then the the new path is a subdirectory and has to be exclusive too
|
||||
vfs::CVirtualLocation *pVLoc = this->getVirtualLocation(sLeft,true);
|
||||
if(pVLoc)
|
||||
{
|
||||
bIsExclusive = pVLoc->getIsExclusive();
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// VFS_THROW(L"location (closest match) should exist");
|
||||
//}
|
||||
bNewLocation = true;
|
||||
}
|
||||
if(pProfLoc && pProfLoc->implementsWritable())
|
||||
{
|
||||
// create file and add to location
|
||||
vfs::TDirectory<vfs::IWritable> *pDir = dynamic_cast<vfs::TDirectory<vfs::IWritable>*>(pProfLoc);
|
||||
vfs::IBaseFile* pFile = pDir->addFile(sFilename);
|
||||
if(bNewLocation)
|
||||
{
|
||||
pProf->addLocation(pProfLoc);
|
||||
}
|
||||
if(pFile)
|
||||
{
|
||||
CVirtualLocation* pLoc = this->getVirtualLocation(sPath,true);
|
||||
if(bIsExclusive)
|
||||
{
|
||||
pLoc->setIsExclusive(bIsExclusive);
|
||||
}
|
||||
pLoc->addFile(pFile,pProf->cName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// throw ?
|
||||
return false;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_dfebug.cpp
|
||||
* - Exception class and throw macros, used to notify the using program of unexpected situations
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
#include <vfs/Core/vfs_string.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <ctime>
|
||||
|
||||
vfs::Exception::Exception(vfs::String const& text, vfs::String const& function, int line, const char* file)
|
||||
: std::exception() //(text.utf8().c_str())
|
||||
{
|
||||
VFS_LOG_ERROR( text.c_str() );
|
||||
|
||||
time_t rawtime;
|
||||
time ( &rawtime );
|
||||
std::string datetime(ctime(&rawtime));
|
||||
|
||||
SEntry en;
|
||||
en.message = text;
|
||||
en.line = line;
|
||||
en.file = file;
|
||||
en.function = function;
|
||||
VFS_IGNOREEXCEPTION(en.time = vfs::String(datetime.substr(0,datetime.length()-1)), false);
|
||||
m_CallStack.push_back(en);
|
||||
};
|
||||
|
||||
vfs::Exception::Exception(vfs::String const& text, vfs::String const& function, int line, const char* file, std::exception& ex)
|
||||
: std::exception() //(text.utf8().c_str())
|
||||
{
|
||||
VFS_LOG_ERROR( text.c_str() );
|
||||
|
||||
if(dynamic_cast<vfs::Exception*>(&ex))
|
||||
{
|
||||
vfs::Exception& vfs_ex = *static_cast<vfs::Exception*>(&ex);
|
||||
m_CallStack.insert(m_CallStack.end(), vfs_ex.m_CallStack.begin(), vfs_ex.m_CallStack.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
SEntry en;
|
||||
en.line = -1;
|
||||
en.file = "";
|
||||
en.function = "";
|
||||
en.time = "";
|
||||
VFS_IGNOREEXCEPTION( en.message = vfs::String(ex.what()), false );
|
||||
|
||||
m_CallStack.push_back(en);
|
||||
}
|
||||
|
||||
time_t rawtime;
|
||||
time ( &rawtime );
|
||||
std::string datetime(ctime(&rawtime));
|
||||
|
||||
SEntry en;
|
||||
en.message = text;
|
||||
en.line = line;
|
||||
en.file = file;
|
||||
en.function = function;
|
||||
VFS_IGNOREEXCEPTION(en.time = vfs::String(datetime.substr(0,datetime.length()-1)), false);
|
||||
|
||||
m_CallStack.push_back(en);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
vfs::Exception::~Exception() throw()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::String vfs::Exception::getLastEntryString() const
|
||||
{
|
||||
if(!m_CallStack.empty())
|
||||
{
|
||||
CALLSTACK::const_reverse_iterator rit = m_CallStack.rbegin();
|
||||
std::wstringstream wss;
|
||||
wss << rit->file.c_wcs()
|
||||
<< L" (l. "
|
||||
<< rit->line
|
||||
<< ") : ["
|
||||
<< rit->function.c_wcs()
|
||||
<< L"] - "
|
||||
<< rit->message.c_wcs();
|
||||
return wss.str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* vfs::Exception::what() const throw()
|
||||
{
|
||||
static std::string msg;
|
||||
msg = "";
|
||||
if(!m_CallStack.empty())
|
||||
{
|
||||
//msg = m_CallStack.front().message.utf8();
|
||||
msg = this->getExceptionString().utf8();
|
||||
}
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
|
||||
vfs::String vfs::Exception::getExceptionString() const
|
||||
{
|
||||
if(!m_CallStack.empty())
|
||||
{
|
||||
std::wstringstream wss;
|
||||
CALLSTACK::const_reverse_iterator rit = m_CallStack.rbegin();
|
||||
for(; rit != m_CallStack.rend(); ++rit)
|
||||
{
|
||||
wss << L"========== " << rit->time << L" ==========\r\n";
|
||||
wss << L"File : " << rit->file << L"\r\n";
|
||||
wss << L"Line : " << rit->line << L"\r\n";
|
||||
wss << L"Location : " << rit->function << L"\r\n\r\n";
|
||||
wss << L" " << rit->message << L"\r\n";
|
||||
}
|
||||
return wss.str();
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
//
|
||||
//void vfs::Exception::writeFile(vfs::Path const& sPath)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// vfs::COpenWriteFile oFile(sPath,true,true);
|
||||
// vfs::String s = this->getExceptionString();
|
||||
// oFile->write(s.utf8().c_str(), s.length());
|
||||
// oFile->close();
|
||||
// }
|
||||
// catch(vfs::Exception &ex)
|
||||
// {
|
||||
// vfs::Exception ex2(L"Could not write exception file into VFS",
|
||||
// _FUNCTION_FORMAT_,__LINE__,__FILE__, ex);
|
||||
// vfs::Exception out("Writing exception to disc failed : is there no writable profile?",
|
||||
// _FUNCTION_FORMAT_,__LINE__,__FILE__, *this);
|
||||
//
|
||||
// out.m_CallStack.insert(out.m_CallStack.begin(), ex.m_CallStack.begin(), ex.m_CallStack.end());
|
||||
//
|
||||
// vfs::Path sDir,sFile;
|
||||
// sPath.splitLast(sDir,sFile);
|
||||
// vfs::CFile oFile(sFile);
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// // can also fail, but there is only so much we can do
|
||||
// vfs::COpenWriteFile file( vfs::tWritableFile::cast(&oFile) );
|
||||
// vfs::String s = out.getExceptionString();
|
||||
// file->write(s.utf8().c_str(), s.length());
|
||||
// }
|
||||
// catch(std::exception &fex)
|
||||
// {
|
||||
// VFS_RETHROW(L"Could write exception file at all",fex);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
|
||||
//
|
||||
//void logException(vfs::Exception const& ex)
|
||||
//{
|
||||
// static bool is_logging = false;
|
||||
// if(is_logging)
|
||||
// {
|
||||
// // drop message
|
||||
// return;
|
||||
// }
|
||||
// //////////////////
|
||||
// is_logging = true;
|
||||
// //////////////////
|
||||
//
|
||||
// static vfs::Log& exlog = *vfs::Log::create(L"game_exceptions.log", false, vfs::Log::FLUSH_IMMEDIATELY);
|
||||
// try
|
||||
// {
|
||||
// exlog << ">>>>>>>>>>>>>>>>>>>>>" << vfs::Log::endl;
|
||||
// exlog << ex.getExceptionString();
|
||||
// exlog << "<<<<<<<<<<<<<<<<<<<<<" << vfs::Log::endl << vfs::Log::endl;
|
||||
// }
|
||||
// catch(...)
|
||||
// {
|
||||
// // don't throw at all
|
||||
// }
|
||||
//
|
||||
// //////////////////
|
||||
// is_logging = false;
|
||||
// //////////////////
|
||||
//}
|
||||
//
|
||||
//void logException(std::exception const& ex)
|
||||
//{
|
||||
// logException(ex.what());
|
||||
//}
|
||||
//
|
||||
//void logException(const wchar_t* ex)
|
||||
//{
|
||||
// logException(vfs::String::as_utf8(ex).c_str());
|
||||
//}
|
||||
//
|
||||
//void logException(const char* ex)
|
||||
//{
|
||||
// static bool is_logging = false;
|
||||
// if(is_logging)
|
||||
// {
|
||||
// // drop message
|
||||
// return;
|
||||
// }
|
||||
// //////////////////
|
||||
// is_logging = true;
|
||||
// //////////////////
|
||||
//
|
||||
// static vfs::Log& exlog = *vfs::Log::create(L"game_exceptions.log", false, vfs::Log::FLUSH_IMMEDIATELY);
|
||||
// try
|
||||
// {
|
||||
// exlog << ">>>>>>>>>>>>>>>>>>>>>" << vfs::Log::endl;
|
||||
// exlog << ex;
|
||||
// exlog << "<<<<<<<<<<<<<<<<<<<<<" << vfs::Log::endl << vfs::Log::endl;
|
||||
// }
|
||||
// catch(...)
|
||||
// {
|
||||
// // don't throw at all
|
||||
// }
|
||||
//
|
||||
// //////////////////
|
||||
// is_logging = false;
|
||||
// //////////////////}
|
||||
//}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_file_raii.cpp
|
||||
* - RAII classes to open files for reading/writing
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
#include <vfs/Core/vfs.h>
|
||||
|
||||
#include <sstream>
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
vfs::COpenReadFile::COpenReadFile(vfs::Path const& sPath, vfs::CVirtualFile::ESearchFile eSF)
|
||||
{
|
||||
vfs::IBaseFile *pFile = getVFS()->getFile(sPath,eSF);
|
||||
VFS_THROW_IFF(pFile, _BS(L"file \"") << sPath << L"\" does not exist" << _BS::wget);
|
||||
|
||||
m_pFile = vfs::tReadableFile::cast(pFile);
|
||||
|
||||
VFS_THROW_IFF(m_pFile, _BS(L"File \"") << sPath << L"\" is not readable" << _BS::wget);
|
||||
|
||||
VFS_THROW_IFF(m_pFile->openRead(), _BS(L"Could not open file : ") << m_pFile->getPath() << _BS::wget);
|
||||
}
|
||||
|
||||
vfs::COpenReadFile::COpenReadFile(vfs::tReadableFile *pFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_pFile = pFile;
|
||||
VFS_THROW_IFF(m_pFile, L"Invalid file object");
|
||||
|
||||
VFS_THROW_IFF(m_pFile->openRead(), _BS(L"Could not open file : ") << pFile->getPath() << _BS::wget);
|
||||
}
|
||||
catch(std::exception &ex)
|
||||
{
|
||||
VFS_RETHROW(L"",ex);
|
||||
}
|
||||
}
|
||||
vfs::COpenReadFile::~COpenReadFile()
|
||||
{
|
||||
if(m_pFile)
|
||||
{
|
||||
m_pFile->close();
|
||||
m_pFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::tReadableFile* vfs::COpenReadFile::operator->()
|
||||
{
|
||||
return m_pFile;
|
||||
}
|
||||
|
||||
vfs::tReadableFile& vfs::COpenReadFile::file()
|
||||
{
|
||||
return *m_pFile;
|
||||
}
|
||||
|
||||
void vfs::COpenReadFile::release()
|
||||
{
|
||||
m_pFile = NULL;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
vfs::COpenWriteFile::COpenWriteFile(vfs::Path const& sPath,
|
||||
bool bCreate,
|
||||
bool bTruncate,
|
||||
vfs::CVirtualFile::ESearchFile eSF)
|
||||
{
|
||||
vfs::IBaseFile *pFile = getVFS()->getFile(sPath,eSF);
|
||||
if(!pFile && bCreate)
|
||||
{
|
||||
if(getVFS()->createNewFile(sPath))
|
||||
{
|
||||
pFile = getVFS()->getFile(sPath,eSF);
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(_BS(L"Could not create VFS file \"") << sPath << L"\"" << _BS::wget);
|
||||
}
|
||||
}
|
||||
VFS_THROW_IFF(pFile, _BS(L"File \"") << sPath << L"\" not found" << _BS::wget);
|
||||
|
||||
m_pFile = vfs::tWritableFile::cast(pFile);
|
||||
|
||||
VFS_THROW_IFF(m_pFile, _BS(L"File \"") << sPath << L"\" exists, but is not writable" << _BS::wget);
|
||||
|
||||
VFS_THROW_IFF(m_pFile->openWrite(bCreate,bTruncate), _BS(L"File \"") << sPath << L"\" could not be opened for writing" << _BS::wget);
|
||||
}
|
||||
vfs::COpenWriteFile::COpenWriteFile(vfs::tWritableFile *pFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_pFile = pFile;
|
||||
VFS_THROW_IFF(m_pFile, L"Invalid file object");
|
||||
VFS_THROW_IFF(m_pFile->openWrite(true,false), _BS(L"Could not open file : ") << m_pFile->getPath() << _BS::wget);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"",ex);
|
||||
};
|
||||
}
|
||||
vfs::COpenWriteFile::~COpenWriteFile()
|
||||
{
|
||||
if(m_pFile)
|
||||
{
|
||||
m_pFile->close();
|
||||
m_pFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
vfs::tWritableFile* vfs::COpenWriteFile::operator->()
|
||||
{
|
||||
return m_pFile;
|
||||
}
|
||||
|
||||
vfs::tWritableFile& vfs::COpenWriteFile::file()
|
||||
{
|
||||
return *m_pFile;
|
||||
}
|
||||
|
||||
void vfs::COpenWriteFile::release()
|
||||
{
|
||||
m_pFile = NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_init.cpp
|
||||
* - initialization functions/classes
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs.h>
|
||||
#include <vfs/Core/vfs_init.h>
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <vfs/Core/File/vfs_buffer_file.h>
|
||||
#include <vfs/Core/Location/vfs_directory_tree.h>
|
||||
#include <vfs/Core/Interface/vfs_library_interface.h>
|
||||
|
||||
#ifdef VFS_WITH_SLF
|
||||
# include <vfs/Ext/slf/vfs_slf_library.h>
|
||||
#endif
|
||||
#ifdef VFS_WITH_7ZIP
|
||||
# include <vfs/Ext/7z/vfs_7z_library.h>
|
||||
# include <vfs/Ext/7z/vfs_create_7z_library.h>
|
||||
#endif
|
||||
|
||||
#include <vfs/Tools/vfs_property_container.h>
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
|
||||
#include <vfs/Aspects/vfs_logging.h>
|
||||
#include <vfs/Aspects/vfs_settings.h>
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
vfs_init::Location::Location()
|
||||
: m_optional(false)
|
||||
{
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
vfs_init::Profile::Profile()
|
||||
: m_writable(false)
|
||||
{
|
||||
};
|
||||
|
||||
vfs_init::Profile::~Profile()
|
||||
{
|
||||
t_locations::iterator it = locations.begin();
|
||||
for(;it != locations.end(); ++it)
|
||||
{
|
||||
if(it->first) delete it->second;
|
||||
}
|
||||
locations.clear();
|
||||
}
|
||||
|
||||
void vfs_init::Profile::addLocation(Location* loc, bool own)
|
||||
{
|
||||
locations.push_back(std::make_pair(own,loc));
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
vfs_init::VfsConfig::~VfsConfig()
|
||||
{
|
||||
t_profiles::iterator it = profiles.begin();
|
||||
for(;it != profiles.end(); ++it)
|
||||
{
|
||||
if(it->first) delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void vfs_init::VfsConfig::addProfile(Profile* prof, bool own)
|
||||
{
|
||||
profiles.push_back(std::make_pair(own,prof));
|
||||
}
|
||||
|
||||
void vfs_init::VfsConfig::appendConfig(VfsConfig& conf)
|
||||
{
|
||||
VfsConfig::t_profiles::iterator it = conf.profiles.begin();
|
||||
for(; it != conf.profiles.end(); ++it)
|
||||
{
|
||||
// even if the other object owns its profiles, this one does not
|
||||
profiles.push_back(std::make_pair(false,it->second));
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************************************************************/
|
||||
|
||||
bool vfs_init::initVirtualFileSystem(vfs::Path const& vfs_ini)
|
||||
{
|
||||
std::list<vfs::Path> li;
|
||||
li.push_back(vfs_ini);
|
||||
return initVirtualFileSystem(li);
|
||||
}
|
||||
bool vfs_init::initVirtualFileSystem(std::list<vfs::Path> const& vfs_ini_list)
|
||||
{
|
||||
vfs::PropertyContainer oVFSProps;
|
||||
std::list<vfs::Path>::const_iterator clit = vfs_ini_list.begin();
|
||||
for(; clit != vfs_ini_list.end(); ++clit)
|
||||
{
|
||||
oVFSProps.initFromIniFile(*clit);
|
||||
}
|
||||
return initVirtualFileSystem(oVFSProps);
|
||||
}
|
||||
bool vfs_init::initVirtualFileSystem(vfs::PropertyContainer& oVFSProps)
|
||||
{
|
||||
VFS_LOG_INFO(L"Processing VFS configuration");
|
||||
vfs_init::VfsConfig conf;
|
||||
|
||||
std::list<vfs::String> lProfiles, lLocSections;
|
||||
|
||||
oVFSProps.getStringListProperty(L"vfs_config",L"PROFILES",lProfiles,L"");
|
||||
if(lProfiles.empty())
|
||||
{
|
||||
VFS_LOG_ERROR(L"no profiles specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<vfs::String>::const_iterator prof_cit = lProfiles.begin();
|
||||
for(; prof_cit != lProfiles.end(); ++prof_cit)
|
||||
{
|
||||
vfs::String sProfSection = vfs::String("PROFILE_") + vfs::String(*prof_cit);
|
||||
|
||||
vfs_init::Profile *prof = new vfs_init::Profile();
|
||||
prof->m_name = oVFSProps.getStringProperty(sProfSection,L"NAME",L"");
|
||||
prof->m_root = oVFSProps.getStringProperty(sProfSection,L"PROFILE_ROOT",L"");
|
||||
prof->m_writable = oVFSProps.getBoolProperty(sProfSection,L"WRITE",false);
|
||||
|
||||
lLocSections.clear();
|
||||
oVFSProps.getStringListProperty(sProfSection,L"LOCATIONS",lLocSections,L"");
|
||||
|
||||
std::list<vfs::String>::iterator loc_it = lLocSections.begin();
|
||||
for(; loc_it != lLocSections.end(); ++loc_it)
|
||||
{
|
||||
vfs::String sLocSection = vfs::String("LOC_") + vfs::String(*loc_it);
|
||||
|
||||
vfs_init::Location *loc = new vfs_init::Location();
|
||||
loc->m_path = oVFSProps.getStringProperty(sLocSection,L"PATH",L"");
|
||||
loc->m_vfs_path = oVFSProps.getStringProperty(sLocSection,L"VFS_PATH",L"");
|
||||
loc->m_mount_point = oVFSProps.getStringProperty(sLocSection,L"MOUNT_POINT",L"");
|
||||
loc->m_type = oVFSProps.getStringProperty(sLocSection,L"TYPE",L"NOT_FOUND");
|
||||
loc->m_optional = oVFSProps.getBoolProperty(sLocSection,L"OPTIONAL",false);
|
||||
|
||||
prof->addLocation(loc,true);
|
||||
}
|
||||
conf.addProfile(prof,true);
|
||||
}
|
||||
return initVirtualFileSystem(conf);
|
||||
}
|
||||
|
||||
bool vfs_init::initWriteProfile(vfs::CVirtualProfile &rProf)
|
||||
{
|
||||
typedef vfs::TDirectory<vfs::IWritable> tWDir;
|
||||
tWDir *pDir = NULL;
|
||||
vfs::IBaseLocation *pLoc = rProf.getLocation(vfs::Path(vfs::Const::EMPTY()));
|
||||
if(pLoc)
|
||||
{
|
||||
pDir = dynamic_cast<tWDir*>(pLoc);
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_LOG_WARNING(_BS(L"Could not find location (\"\") for profile '") << rProf.cName << L"'" << _BS::wget );
|
||||
VFS_LOG_WARNING(_BS(L"Trying to initialize profile root : ") << rProf.cRoot << _BS::wget );
|
||||
vfs::CDirectoryTree *pDirTree = NULL;
|
||||
pDirTree = new vfs::CDirectoryTree(vfs::Path(vfs::Const::EMPTY()),rProf.cRoot);
|
||||
if(!pDirTree->init())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
VFS_TRYCATCH_RETHROW( rProf.addLocation(pDirTree), L"" );
|
||||
getVFS()->addLocation(pDirTree, &rProf);
|
||||
pDir = pDirTree;
|
||||
}
|
||||
return pDir != NULL;
|
||||
}
|
||||
|
||||
|
||||
bool vfs_init::initVirtualFileSystem(vfs_init::VfsConfig const& conf)
|
||||
{
|
||||
VFS_LOG_INFO(L"Initializing Virtual File System");
|
||||
|
||||
vfs::CVirtualFileSystem *pVFS = getVFS();
|
||||
|
||||
if(conf.profiles.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vfs_init::VfsConfig::t_profiles::const_iterator prof_it = conf.profiles.begin();
|
||||
for(; prof_it != conf.profiles.end(); ++prof_it)
|
||||
{
|
||||
vfs_init::Profile* prof = prof_it->second;
|
||||
VFS_LOG_INFO(_BS(L" Reading profile : ") << prof->m_name << _BS::wget);
|
||||
|
||||
vfs::Path profileRoot = prof->m_root;
|
||||
|
||||
bool bIsWritable = prof->m_writable;
|
||||
|
||||
vfs::CProfileStack *pPS = pVFS->getProfileStack();
|
||||
vfs::CVirtualProfile *pProf = pPS->getProfile(prof->m_name);
|
||||
if(!pProf)
|
||||
{
|
||||
pProf = new vfs::CVirtualProfile(prof->m_name, profileRoot, bIsWritable);
|
||||
pPS->pushProfile(pProf);
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW_IFF(pProf->cWritable == bIsWritable, L"profile already exists, but their write properties differ");
|
||||
VFS_THROW_IFF(pProf->cRoot == profileRoot, L"profile already exists, but their root directories differ");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
vfs_init::Profile::t_locations::iterator loc_it = prof->locations.begin();
|
||||
loc_it = prof->locations.begin();
|
||||
for(; loc_it != prof->locations.end(); ++loc_it)
|
||||
{
|
||||
vfs_init::Location *loc = loc_it->second;
|
||||
|
||||
bool bOptional = loc->m_optional;
|
||||
if(vfs::StrCmp::Equal(loc->m_type,L"LIBRARY"))
|
||||
{
|
||||
vfs::tReadableFile *pLibFile = NULL;
|
||||
bool bOwnFile = false;
|
||||
|
||||
vfs::Path fullpath = profileRoot + loc->m_path;
|
||||
VFS_LOG_INFO( _BS(L" library : \"") << fullpath << L"\"" << _BS::wget );
|
||||
|
||||
if(!loc->m_path.empty())
|
||||
{
|
||||
// try regular file
|
||||
pLibFile = vfs::tReadableFile::cast( new vfs::CFile(fullpath) );
|
||||
bOwnFile = true;
|
||||
}
|
||||
if(!pLibFile && !loc->m_vfs_path.empty())
|
||||
{
|
||||
// if regular file doesn't exist, try to find it in the (partially initialized) VFS
|
||||
pLibFile = pVFS->getReadFile(profileRoot + loc->m_vfs_path);
|
||||
}
|
||||
if(pLibFile)
|
||||
{
|
||||
vfs::String full_str = pLibFile->getName()();
|
||||
vfs::String ext = full_str.c_wcs().substr(full_str.length()-3,3);
|
||||
vfs::ILibrary *pLib = NULL;
|
||||
if(vfs::StrCmp::Equal(ext,L"slf"))
|
||||
{
|
||||
#ifdef VFS_WITH_SLF
|
||||
pLib = new vfs::CSLFLibrary( pLibFile, loc->m_mount_point );
|
||||
#else
|
||||
VFS_LOG_ERROR(L"Trying to init slf library : SLF support disabled");
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
else if(vfs::StrCmp::Equal(ext,L".7z"))
|
||||
{
|
||||
#ifdef VFS_WITH_7ZIP
|
||||
pLib = new vfs::CUncompressed7zLibrary( pLibFile, loc->m_mount_point );
|
||||
#else
|
||||
VFS_LOG_ERROR(L"Trying to init 7z library : 7zip support disabled");
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(_BS(L"File [") << loc->m_path << L"] in not an SLF or 7z library" << _BS::wget);
|
||||
}
|
||||
if(!pLib->init())
|
||||
{
|
||||
if(!bOptional)
|
||||
{
|
||||
VFS_THROW(_BS(L"Could not initialize library [ ") << loc->m_path << L" ]" <<
|
||||
L" in : profile [ " << prof->m_name << L" ]," <<
|
||||
L" path [ " << fullpath << L" ]" << _BS::wget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pProf->addLocation(pLib);
|
||||
pVFS->addLocation(vfs::tReadLocation::cast(pLib), pProf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(_BS(L"File not found : ") << loc->m_path << _BS::wget);
|
||||
}
|
||||
}
|
||||
else if(vfs::StrCmp::Equal(loc->m_type,L"DIRECTORY"))
|
||||
{
|
||||
vfs::Path fullpath = profileRoot + loc->m_path;
|
||||
VFS_LOG_INFO( _BS(L" directory : \"") << fullpath << L"\"" << _BS::wget );
|
||||
|
||||
vfs::IBaseLocation *pDirLocation = NULL;
|
||||
bool init_success = false;
|
||||
if(bIsWritable)
|
||||
{
|
||||
vfs::CDirectoryTree *pDirTree = new vfs::CDirectoryTree(loc->m_mount_point, fullpath);
|
||||
init_success = pDirTree->init();
|
||||
pDirLocation = pDirTree;
|
||||
}
|
||||
else
|
||||
{
|
||||
vfs::CReadOnlyDirectoryTree *pDirTree = new vfs::CReadOnlyDirectoryTree(loc->m_mount_point, fullpath);
|
||||
init_success = pDirTree->init();
|
||||
pDirLocation = pDirTree;
|
||||
}
|
||||
if(!init_success)
|
||||
{
|
||||
VFS_THROW(_BS(L"Could not initialize directory [\"") << loc->m_path << L"\"]" <<
|
||||
L" in : profile [\"" << prof->m_name << L"\"]," <<
|
||||
L" path [\"" << fullpath << L"\"]" << _BS::wget);
|
||||
}
|
||||
else
|
||||
{
|
||||
pProf->addLocation(pDirLocation);
|
||||
pVFS->addLocation(pDirLocation, pProf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bIsWritable)
|
||||
{
|
||||
vfs::CProfileStack *pPS = pVFS->getProfileStack();
|
||||
vfs::CVirtualProfile *pProf = pPS->getProfile(prof->m_name);
|
||||
if(!pProf)
|
||||
{
|
||||
pProf = new vfs::CVirtualProfile(prof->m_name,profileRoot,true);
|
||||
pPS->pushProfile(pProf);
|
||||
}
|
||||
else if(!pProf->cWritable)
|
||||
{
|
||||
VFS_THROW(_BS(L"Profile [") << prof->m_name << L"] is supposed to be writable!" << _BS::wget);
|
||||
}
|
||||
initWriteProfile(*pProf);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/os_functions.cpp
|
||||
* - abstractions for OS dependant code
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
#include <vfs/Core/vfs_string.h>
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
#include <vfs/Aspects/vfs_settings.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef WIN32
|
||||
# include "errno.h"
|
||||
# include "sys/stat.h"
|
||||
#endif
|
||||
|
||||
vfs::OS::CIterateDirectory::CIterateDirectory(vfs::Path const& sPath, vfs::String const& searchPattern)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(!vfs::Settings::getUseUnicode())
|
||||
{
|
||||
std::string s;
|
||||
vfs::String::narrow((sPath+searchPattern).c_wcs(), s);
|
||||
fSearchHandle = FindFirstFileA(s.c_str(), &fFileInfoA);
|
||||
}
|
||||
else
|
||||
{
|
||||
fSearchHandle = FindFirstFileW((sPath+searchPattern).c_wcs().c_str(), &fFileInfoW);
|
||||
}
|
||||
if (fSearchHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
VFS_THROW(_BS(L"Error accessing path [") << (sPath+searchPattern) << L"], error code : " << error << _BS::wget);
|
||||
}
|
||||
#else
|
||||
count = scandir(vfs::String::as_utf8(sPath()).c_str(),&files,NULL,NULL);
|
||||
if(count == -1)
|
||||
{
|
||||
vfs::String err = strerror(errno);
|
||||
VFS_THROW(err);
|
||||
}
|
||||
current_pos = 0;
|
||||
#endif
|
||||
fFirstRequest = true;
|
||||
}
|
||||
|
||||
vfs::OS::CIterateDirectory::~CIterateDirectory()
|
||||
{
|
||||
#ifdef WIN32
|
||||
FindClose(fSearchHandle);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
bool vfs::OS::CIterateDirectory::nextFile(vfs::String &fileName, CIterateDirectory::EFileAttribute &attrib)
|
||||
{
|
||||
#ifdef WIN32
|
||||
VFS_THROW_IFF(fSearchHandle != INVALID_HANDLE_VALUE, L"Invalid Handle Value");
|
||||
if (fFirstRequest)
|
||||
{
|
||||
fFirstRequest = false;
|
||||
}
|
||||
//else
|
||||
{
|
||||
if(!vfs::Settings::getUseUnicode())
|
||||
{
|
||||
if( !FindNextFileA(fSearchHandle, &fFileInfoA) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fileName.r_wcs().assign( vfs::String::widen( fFileInfoA.cFileName, strlen(fFileInfoA.cFileName) ) );
|
||||
attrib = (fFileInfoA.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? CIterateDirectory::FA_DIRECTORY : CIterateDirectory::FA_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !FindNextFileW(fSearchHandle, &fFileInfoW) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fileName.r_wcs().assign(fFileInfoW.cFileName);
|
||||
attrib = (fFileInfoW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? CIterateDirectory::FA_DIRECTORY : CIterateDirectory::FA_FILE;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
if(current_pos < count)
|
||||
{
|
||||
struct dirent* entry = files[current_pos];
|
||||
fileName = vfs::String(entry->d_name);
|
||||
attrib = (entry->d_type == DT_DIR) ? CIterateDirectory::FA_DIRECTORY : CIterateDirectory::FA_FILE;
|
||||
current_pos++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool vfs::OS::checkRealDirectory(vfs::Path const& sDir)
|
||||
{
|
||||
#ifdef WIN32
|
||||
bool bDirExists = false;
|
||||
if(!vfs::Settings::getUseUnicode())
|
||||
{
|
||||
WIN32_FIND_DATAA fd;
|
||||
memset(&fd,0,sizeof(WIN32_FIND_DATAA));
|
||||
|
||||
std::string s;
|
||||
vfs::String::narrow(sDir.c_wcs(), s);
|
||||
|
||||
HANDLE hFile = FindFirstFileA( s.c_str(), &fd);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
VFS_LOG_ERROR(_BS(L"Directory [") << sDir << L"] does not exist : " << error << _BS::wget);
|
||||
}
|
||||
|
||||
bDirExists = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0;
|
||||
|
||||
FindClose(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIN32_FIND_DATAW fd;
|
||||
memset(&fd,0,sizeof(WIN32_FIND_DATAW));
|
||||
HANDLE hFile = FindFirstFileW( sDir.c_str(), &fd);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
VFS_LOG_ERROR(_BS(L"Directory [") << sDir << L"] does not exist : " << error << _BS::wget);
|
||||
}
|
||||
|
||||
bDirExists = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) > 0;
|
||||
|
||||
FindClose(hFile);
|
||||
}
|
||||
return bDirExists;
|
||||
#else
|
||||
int result = access(sDir.to_string().c_str(), F_OK /*0400*/);
|
||||
if(result == -1)
|
||||
{
|
||||
vfs::String err = strerror(errno);
|
||||
VFS_LOG_ERROR(err.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool vfs::OS::createRealDirectory(vfs::Path const& sDir)
|
||||
{
|
||||
#ifdef WIN32
|
||||
BOOL success;
|
||||
vfs::String::str_t const& str = sDir.c_wcs();
|
||||
success = vfs::Settings::getUseUnicode() ?
|
||||
CreateDirectoryW(sDir.c_str(),NULL) :
|
||||
CreateDirectoryA( vfs::String::narrow( str.c_str(), str.length() ).c_str(), NULL );
|
||||
if(success == 0)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
if(error == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
VFS_LOG_ERROR((_BS("Could not create directory [") << sDir << L"] : " << error).get());
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
int result = mkdir(sDir.to_string().c_str(), S_IRWXU | S_IRGRP /*0777*/);
|
||||
if(result == -1 && errno != EEXIST)
|
||||
{
|
||||
vfs::String err = strerror(errno);
|
||||
VFS_THROW(err);
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool vfs::OS::FileAttributes::getFileAttributes(vfs::Path const& sDir, vfs::UInt32& uiAttribs)
|
||||
{
|
||||
#ifdef WIN32
|
||||
DWORD attribs = vfs::Settings::getUseUnicode() ?
|
||||
GetFileAttributesW(sDir.c_str()) :
|
||||
GetFileAttributesA(vfs::String::narrow(sDir.c_str(), sDir.length()).c_str());
|
||||
|
||||
if(attribs == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
VFS_LOG_ERROR(_BS(L"Invalid File Attributes : ") << error << _BS::wget);
|
||||
return false;
|
||||
}
|
||||
|
||||
for(vfs::UInt32 attribMask = 0x80000000; attribMask > 0; attribMask >>= 1)
|
||||
{
|
||||
switch(attribs & attribMask)
|
||||
{
|
||||
case FILE_ATTRIBUTE_ARCHIVE:
|
||||
uiAttribs |= ATTRIB_ARCHIVE;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_DIRECTORY:
|
||||
uiAttribs |= ATTRIB_DIRECTORY;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_HIDDEN:
|
||||
uiAttribs |= ATTRIB_HIDDEN;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_NORMAL:
|
||||
uiAttribs |= ATTRIB_NORMAL;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_READONLY:
|
||||
uiAttribs |= ATTRIB_READONLY;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_SYSTEM:
|
||||
uiAttribs |= ATTRIB_SYSTEM;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_TEMPORARY:
|
||||
uiAttribs |= ATTRIB_TEMPORARY;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_COMPRESSED:
|
||||
uiAttribs |= ATTRIB_COMPRESSED;
|
||||
break;
|
||||
case FILE_ATTRIBUTE_OFFLINE:
|
||||
uiAttribs |= ATTRIB_OFFLINE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::OS::deleteRealFile(vfs::Path const& sDir)
|
||||
{
|
||||
#ifdef WIN32
|
||||
BOOL del = vfs::Settings::getUseUnicode() ?
|
||||
DeleteFileW( sDir.c_str() ) :
|
||||
DeleteFileA( vfs::String::narrow(sDir.c_str(), sDir.length()).c_str() );
|
||||
if(!del)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if(err != NO_ERROR)
|
||||
{
|
||||
VFS_LOG_ERROR(L"Could not delete file");
|
||||
}
|
||||
}
|
||||
return (del != FALSE);
|
||||
#else
|
||||
return (remove( vfs::String::as_utf8(sDir()).c_str() ) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void vfs::OS::getExecutablePath(vfs::Path& sDir, vfs::Path& sFile)
|
||||
{
|
||||
#ifdef WIN32
|
||||
DWORD error;
|
||||
if(!vfs::Settings::getUseUnicode())
|
||||
{
|
||||
char path[256];
|
||||
if( 0 != (error = ::GetModuleFileNameA(NULL, path, 256)) )
|
||||
{
|
||||
vfs::Path(vfs::String::widen(path,256)).splitLast(sDir, sFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t path[256];
|
||||
if( 0 != (error = ::GetModuleFileNameW(NULL, path, 256)) )
|
||||
{
|
||||
vfs::Path(path).splitLast(sDir, sFile);
|
||||
}
|
||||
}
|
||||
if(error == 0)
|
||||
{
|
||||
DWORD code = GetLastError();
|
||||
VFS_THROW(_BS(L"Could not get current directory [") <<
|
||||
(!vfs::Settings::getUseUnicode() ? L"no unicode" : L"unicode") <<
|
||||
L"], error code : " << code << _BS::wget);
|
||||
}
|
||||
#else
|
||||
char buf[256];
|
||||
ssize_t size = readlink("/proc/self/exe", buf, 256);
|
||||
if(size == -1)
|
||||
{
|
||||
vfs::String err = strerror(errno);
|
||||
VFS_THROW(err);
|
||||
}
|
||||
buf[size] = 0;
|
||||
vfs::Path exedir(buf);
|
||||
exedir.splitLast(sDir, sFile);
|
||||
#endif
|
||||
}
|
||||
|
||||
void vfs::OS::getCurrentDirectory(vfs::Path& sPath)
|
||||
{
|
||||
#ifdef WIN32
|
||||
DWORD error;
|
||||
vfs::Path path;
|
||||
if( !vfs::Settings::getUseUnicode() )
|
||||
{
|
||||
char path[256];
|
||||
if( 0 != (error = ::GetCurrentDirectoryA(256, path)) )
|
||||
{
|
||||
sPath = vfs::Path(vfs::String::widen(path,256));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t path[256];
|
||||
if( 0 != (error = ::GetCurrentDirectoryW(256, path)) )
|
||||
{
|
||||
sPath = vfs::Path(path);
|
||||
}
|
||||
}
|
||||
if(error == 0)
|
||||
{
|
||||
DWORD code = GetLastError();
|
||||
VFS_THROW(_BS(L"Could not determine current directory ") <<
|
||||
(!vfs::Settings::getUseUnicode() ? L"[no unicode]" : L"[unicode]") <<
|
||||
L", error code : " << _BS::wget);
|
||||
}
|
||||
#else
|
||||
char* cwd = getcwd(NULL,0);
|
||||
if(!cwd)
|
||||
{
|
||||
vfs::String err = strerror(errno);
|
||||
VFS_THROW(err);
|
||||
}
|
||||
sPath = cwd;
|
||||
free(cwd);
|
||||
#endif
|
||||
}
|
||||
|
||||
void vfs::OS::setCurrectDirectory(vfs::Path const& sPath)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(!vfs::Settings::getUseUnicode())
|
||||
{
|
||||
std::string str;
|
||||
vfs::String::narrow( sPath.c_wcs(), str );
|
||||
VFS_THROW_IFF( ::SetCurrentDirectoryA( str.c_str() ) == TRUE,
|
||||
_BS(L"Could not set current directory [no unicode] : ") << sPath << _BS::wget );
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW_IFF( ::SetCurrentDirectoryW( sPath.c_str() ) == TRUE,
|
||||
_BS(L"Could not set current directory [unicode] : ") << sPath <<_BS::wget );
|
||||
}
|
||||
#else
|
||||
if(chdir(sPath.to_string().c_str()) != 0)
|
||||
{
|
||||
vfs::String err = strerror(errno);
|
||||
VFS_THROW(err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool vfs::OS::getEnv(vfs::String const& key, vfs::String& value)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
wchar_t *val_buf = NULL;
|
||||
::size_t buf_len;
|
||||
errno_t err = _wdupenv_s(&val_buf,&buf_len, key.c_str());
|
||||
if(err == 0 && val_buf)
|
||||
{
|
||||
// success
|
||||
value = val_buf;
|
||||
free(val_buf);
|
||||
}
|
||||
return err == 0;
|
||||
#else
|
||||
char* val_buf = getenv(key.utf8().c_str());
|
||||
if(val_buf)
|
||||
{
|
||||
value = val_buf;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_path.cpp
|
||||
* - Path class, stores and validates a file/directory path string, offers meaningful path operations
|
||||
* - path comparison functions (operator overloading)
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_path.h>
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
|
||||
#include <vfs/Aspects/vfs_settings.h>
|
||||
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
typedef struct{ vfs::String::size_t start, end; } t_env;
|
||||
|
||||
bool vfs::Path::expandEnv()
|
||||
{
|
||||
vfs::String::ptr_t raw_ptr = &_path[0];
|
||||
std::stack<t_env> pos;
|
||||
vfs::Int32 pos_start = -1, pos_end = -1, pos_current = 0;
|
||||
while(*raw_ptr != 0)
|
||||
{
|
||||
if(*raw_ptr == L'$')
|
||||
{
|
||||
pos_start = pos_current;
|
||||
}
|
||||
else if(pos_start >= 0)
|
||||
{
|
||||
if(*raw_ptr == '(' && pos_current == (pos_start+1))
|
||||
{
|
||||
// ensure the syntax $(VARNAME) is followed
|
||||
pos_end = pos_start;
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// pos_start = pos_end = -1;
|
||||
//}
|
||||
else if(pos_start == pos_end && *raw_ptr == ')')
|
||||
{
|
||||
pos_end = pos_current;
|
||||
}
|
||||
//
|
||||
if(pos_end >= 0 && pos_start != pos_end)
|
||||
{
|
||||
t_env e;
|
||||
e.start = pos_start;
|
||||
e.end = pos_end;
|
||||
pos.push(e);
|
||||
pos_start = pos_end = -1;
|
||||
}
|
||||
}
|
||||
pos_current++;
|
||||
raw_ptr++;
|
||||
}
|
||||
if(!pos.empty())
|
||||
{
|
||||
while(!pos.empty())
|
||||
{
|
||||
t_env v = pos.top();
|
||||
vfs::String var_name = _path.substr(v.start+2, v.end-v.start-2);
|
||||
vfs::String var_value;
|
||||
if(!vfs::OS::getEnv(var_name, var_value))
|
||||
{
|
||||
VFS_LOG_WARNING(_BS(L"Could not expand environment variable : ") << var_name << _BS::wget);
|
||||
return false;
|
||||
}
|
||||
_path.replace(v.start,v.end-v.start+1,var_value.c_wcs());
|
||||
pos.pop();
|
||||
}
|
||||
doCheck();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void unifySeparators(vfs::String::str_t &sPath)
|
||||
{
|
||||
vfs::String::char_t &raw = sPath[0];
|
||||
vfs::String::ptr_t raw_ptr = &raw;
|
||||
while(*raw_ptr != 0)
|
||||
{
|
||||
if(*raw_ptr == '\\' || *raw_ptr == '/')
|
||||
{
|
||||
*raw_ptr = vfs::Const::SEPARATOR_CHAR();
|
||||
}
|
||||
raw_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* call after unifying separators
|
||||
*/
|
||||
static vfs::UInt32 removeSeparators(vfs::String::str_t &str)
|
||||
{
|
||||
vfs::UInt32 sepcount = 0;
|
||||
vfs::Int32 numsep = 0;
|
||||
::size_t put_pos = 0;
|
||||
::size_t len = str.length();
|
||||
vfs::String::char_t& raw = str[0];
|
||||
vfs::String::ptr_t old_ptr = &raw;
|
||||
vfs::String::ptr_t new_ptr = &raw;
|
||||
vfs::String::ptr_t last_ptr = &raw;
|
||||
vfs::String::char_t sep = vfs::Const::SEPARATOR_CHAR();
|
||||
while(*old_ptr != 0)
|
||||
{
|
||||
if(*old_ptr == sep)
|
||||
{
|
||||
numsep++;
|
||||
if(numsep == 1)
|
||||
{
|
||||
sepcount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have normal text (again)
|
||||
numsep = 0;
|
||||
}
|
||||
if(numsep <= 1)
|
||||
{
|
||||
*new_ptr = *old_ptr;
|
||||
last_ptr = new_ptr++;
|
||||
put_pos++;
|
||||
}
|
||||
old_ptr++;
|
||||
}
|
||||
if(*last_ptr == sep)
|
||||
{
|
||||
put_pos--;
|
||||
if(sepcount>0)
|
||||
{
|
||||
sepcount--;
|
||||
}
|
||||
}
|
||||
if(put_pos < len)
|
||||
{
|
||||
str.erase(put_pos);
|
||||
}
|
||||
return sepcount;
|
||||
}
|
||||
|
||||
static void removeLastSeparator(vfs::String::str_t &str)
|
||||
{
|
||||
if( *str.rbegin() == vfs::Const::SEPARATOR_CHAR() )
|
||||
{
|
||||
str.erase( str.length()-1);
|
||||
}
|
||||
}
|
||||
|
||||
static void removeDots(vfs::String::str_t &str, vfs::UInt32 number_of_separators)
|
||||
{
|
||||
vfs::String::char_t& raw = str[0];
|
||||
vfs::String::ptr_t old_ptr = &raw;
|
||||
vfs::String::ptr_t new_ptr = &raw;
|
||||
vfs::String::size_t LENGTH = str.length();
|
||||
bool dirty = false;
|
||||
|
||||
// see if we start with ./ (not . as this might be a hidden files on unix systems)
|
||||
if( (LENGTH > 1) && (*old_ptr == vfs::Const::DOT_CHAR()) && (*(old_ptr+1) == vfs::Const::SEPARATOR_CHAR()) )
|
||||
{
|
||||
old_ptr += 2;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
std::vector<vfs::String::ptr_t> sub_strings;
|
||||
sub_strings.resize(number_of_separators);
|
||||
int pos=0;
|
||||
|
||||
if(*old_ptr != 0 && *old_ptr == vfs::Const::SEPARATOR_CHAR())
|
||||
{
|
||||
if(!dirty)
|
||||
{
|
||||
// in-place : just move along
|
||||
new_ptr++;
|
||||
old_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*new_ptr++ = *old_ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
sub_strings[pos++] = new_ptr;
|
||||
|
||||
while(*old_ptr != 0)
|
||||
{
|
||||
if(*old_ptr != vfs::Const::SEPARATOR_CHAR())
|
||||
{
|
||||
if(!dirty)
|
||||
{
|
||||
new_ptr++;
|
||||
old_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*new_ptr++ = *old_ptr++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
*new_ptr++ = *old_ptr++;
|
||||
sub_strings[pos++] = new_ptr;
|
||||
|
||||
if((&raw+3) < old_ptr)
|
||||
{
|
||||
if( (*(old_ptr-4) == vfs::Const::SEPARATOR_CHAR()) &&
|
||||
(*(old_ptr-3) == vfs::Const::DOT_CHAR()) &&
|
||||
(*(old_ptr-2) == vfs::Const::DOT_CHAR()) &&
|
||||
(*(old_ptr-1) == vfs::Const::SEPARATOR_CHAR()) )
|
||||
{
|
||||
if(pos > 1)
|
||||
{
|
||||
new_ptr = sub_strings[pos-3];
|
||||
pos -= 2;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
else if((*(old_ptr-3) == vfs::Const::SEPARATOR_CHAR()) &&
|
||||
(*(old_ptr-2) == vfs::Const::DOT_CHAR()) &&
|
||||
(*(old_ptr-1) == vfs::Const::SEPARATOR_CHAR()) )
|
||||
{
|
||||
if(pos > 0)
|
||||
{
|
||||
new_ptr = sub_strings[pos-2];
|
||||
pos -= 1;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((&raw+2) < old_ptr)
|
||||
{
|
||||
if( (*(old_ptr-3) == vfs::Const::SEPARATOR_CHAR()) &&
|
||||
(*(old_ptr-2) == vfs::Const::DOT_CHAR()) &&
|
||||
(*(old_ptr-1) == vfs::Const::SEPARATOR_CHAR()) )
|
||||
{
|
||||
if(pos > 0)
|
||||
{
|
||||
new_ptr = sub_strings[pos-2];
|
||||
pos -= 1;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::size_t ttt = (new_ptr - &raw);
|
||||
if(ttt < LENGTH)
|
||||
{
|
||||
str.erase(ttt);
|
||||
}
|
||||
}
|
||||
|
||||
static void getFirstLastSeparator(const vfs::String::char_t* sPath, vfs::size_t &iFirst, vfs::size_t &iLast)
|
||||
{
|
||||
iFirst = vfs::npos;
|
||||
iLast = vfs::npos;
|
||||
const vfs::String::char_t* ptr = sPath;
|
||||
vfs::size_t pos = 0;
|
||||
while(*ptr != 0)
|
||||
{
|
||||
if(*ptr == vfs::Const::SEPARATOR_CHAR())
|
||||
{
|
||||
if(iFirst == vfs::npos)
|
||||
{
|
||||
iFirst = pos;
|
||||
}
|
||||
iLast = pos;
|
||||
}
|
||||
pos++;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool vfs::Path::Less::operator ()(vfs::Path const& s1, vfs::Path const& s2) const
|
||||
{
|
||||
return vfs::String::less(s1._path.c_str(), s2._path.c_str());
|
||||
}
|
||||
bool vfs::Path::Equal::operator ()(vfs::Path const& s1, vfs::Path const& s2) const
|
||||
{
|
||||
return vfs::String::equal(s1._path.c_str(), s2._path.c_str());
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
vfs::Path::Path()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::Path::Path(vfs::String const& sPath)
|
||||
: _path(sPath.c_wcs())
|
||||
{
|
||||
doCheck();
|
||||
}
|
||||
|
||||
vfs::Path::Path(const char* sPath)
|
||||
{
|
||||
if(vfs::Settings::getUseUnicode())
|
||||
{
|
||||
vfs::String::as_utf16(sPath,_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
vfs::String::widen(std::string(sPath),_path);
|
||||
}
|
||||
doCheck();
|
||||
}
|
||||
|
||||
vfs::Path::Path(std::string const& sPath)
|
||||
{
|
||||
if(vfs::Settings::getUseUnicode())
|
||||
{
|
||||
vfs::String::as_utf16(sPath,_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
vfs::String::widen(sPath,_path);
|
||||
}
|
||||
doCheck();
|
||||
}
|
||||
|
||||
vfs::Path::Path(const wchar_t* sPath)
|
||||
: _path(sPath)
|
||||
{
|
||||
doCheck();
|
||||
}
|
||||
|
||||
const vfs::String::char_t* vfs::Path::c_str() const
|
||||
{
|
||||
return _path.c_str();
|
||||
}
|
||||
|
||||
const vfs::String::str_t& vfs::Path::c_wcs() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
const vfs::String::str_t& vfs::Path::operator()() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
std::string vfs::Path::to_string() const
|
||||
{
|
||||
if(vfs::Settings::getUseUnicode())
|
||||
{
|
||||
return vfs::String::as_utf8(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string s;
|
||||
vfs::String::narrow(_path,s);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::Path::empty() const
|
||||
{
|
||||
// is there a case where a non-empty string can become empty after a check?
|
||||
// if it is so then i don't care
|
||||
return _path.empty();
|
||||
}
|
||||
vfs::String::size_t vfs::Path::length() const
|
||||
{
|
||||
return _path.length();
|
||||
}
|
||||
|
||||
|
||||
void vfs::Path::doCheck()
|
||||
{
|
||||
if(!_path.empty())
|
||||
{
|
||||
unifySeparators(_path);
|
||||
|
||||
vfs::UInt32 number_of_separators = removeSeparators(_path);
|
||||
|
||||
if(number_of_separators>0)
|
||||
{
|
||||
removeDots(_path,number_of_separators+1);
|
||||
getFirstLastSeparator(_path.c_str(),_sep.first,_sep.last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pathSplitLast(vfs::String::str_t const& path,
|
||||
vfs::String::str_t &head,
|
||||
vfs::String::str_t &last,
|
||||
vfs::size_t const& sep_first,
|
||||
vfs::size_t const& sep_last)
|
||||
{
|
||||
if(path.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(&head == &path || &last == &path)
|
||||
{
|
||||
VFS_THROW(L"cannot use output parameters that are equal to 'this'");
|
||||
}
|
||||
#if 1
|
||||
// use results from "GetFirstLastSeparator(..)"
|
||||
if(sep_last != vfs::npos)
|
||||
{
|
||||
head.assign(path.substr(0,sep_last));
|
||||
last.assign(path.substr(sep_last+1, path.length()-sep_last-1));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
vfs::String::size_t position = path.length();
|
||||
while(--position != vfs::npos)
|
||||
{
|
||||
vfs::String::char_t const& c = path.at(position);
|
||||
if(c == '\\' || c == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(position != vfs::npos)
|
||||
{
|
||||
head.assign(path.substr(0,position++));
|
||||
last.assign(path.substr(position,path.length()-position));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
head.assign(vfs::Const::EMPTY());
|
||||
last.assign(path);
|
||||
}
|
||||
|
||||
|
||||
void vfs::Path::splitLast(vfs::Path &rsHead, vfs::Path &rsLast) const
|
||||
{
|
||||
|
||||
pathSplitLast(_path, rsHead._path, rsLast._path, _sep.first, _sep.last);
|
||||
getFirstLastSeparator(rsHead.c_str(), rsHead._sep.first, rsHead._sep.last);
|
||||
getFirstLastSeparator(rsLast.c_str(), rsLast._sep.first, rsLast._sep.last);
|
||||
// no need to check, as the original path is already checked
|
||||
//rPath.DoCheck();
|
||||
//rFile.DoCheck();
|
||||
}
|
||||
|
||||
static void pathSplitFirst(vfs::String::str_t const& path,
|
||||
vfs::String::str_t &first,
|
||||
vfs::String::str_t &tail,
|
||||
vfs::size_t const& sep_first,
|
||||
vfs::size_t const& sep_last)
|
||||
{
|
||||
if(path.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(&first == &path || &tail == &path)
|
||||
{
|
||||
VFS_THROW(L"cannot use output parameters that are equal to 'this'");
|
||||
}
|
||||
|
||||
#if 1
|
||||
// use results from "GetFirstLastSeparator(..)"
|
||||
if(sep_first != vfs::npos)
|
||||
{
|
||||
first.assign(path.substr(0,sep_first));
|
||||
tail.assign(path.substr(sep_first+1, path.length()-sep_first-1));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
vfs::String::size_t position = 0;
|
||||
while(position < path.length())
|
||||
{
|
||||
vfs::String::char_t const& c = path.at(position);
|
||||
if(c == '\\' || c == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
if(position < path.length())
|
||||
{
|
||||
first.assign(path.substr(0,position++));
|
||||
tail.assign(path.substr(position,path.length()-position));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
first.assign(path);
|
||||
tail.assign(vfs::Const::EMPTY());
|
||||
}
|
||||
|
||||
void vfs::Path::splitFirst(vfs::Path &rsFirst, vfs::Path &rsTail) const
|
||||
{
|
||||
pathSplitFirst(_path, rsFirst._path, rsTail._path, _sep.first, _sep.last);
|
||||
getFirstLastSeparator(rsFirst.c_str(), rsFirst._sep.first, rsFirst._sep.last);
|
||||
getFirstLastSeparator(rsTail.c_str(), rsTail._sep.first, rsTail._sep.last);
|
||||
// no need to check, as the original path is already checked
|
||||
//rPath.doCheck();
|
||||
//rFile.doCheck();
|
||||
}
|
||||
|
||||
bool vfs::Path::extension(vfs::String &sExt) const
|
||||
{
|
||||
if(_path.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vfs::String::size_t SIZE = _path.length();
|
||||
if(_path.at(SIZE-1) == L'.')
|
||||
{
|
||||
// not an extension
|
||||
return false;
|
||||
}
|
||||
for(vfs::String::size_t i=SIZE-2; i > 0; i--)
|
||||
{
|
||||
if(_path.at(i) == L'.')
|
||||
{
|
||||
sExt.r_wcs().assign(&_path.at(i+1),SIZE-i-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs::Path& vfs::Path::operator+=(vfs::String const& p)
|
||||
{
|
||||
return *this += vfs::Path(p);
|
||||
}
|
||||
|
||||
vfs::Path& vfs::Path::operator+=(vfs::Path const& p)
|
||||
{
|
||||
if(_path.empty())
|
||||
{
|
||||
_path = p._path;
|
||||
}
|
||||
else if(!p.empty())
|
||||
{
|
||||
_path += vfs::Const::SEPARATOR();
|
||||
_path += p._path;
|
||||
getFirstLastSeparator(_path.c_str(),_sep.first,_sep.last);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vfs::Path operator+(vfs::Path const& p1, vfs::Path const& p2)
|
||||
{
|
||||
vfs::Path newpath = p1;
|
||||
newpath += p2;
|
||||
return newpath;
|
||||
}
|
||||
|
||||
bool vfs::Path::operator==(vfs::Path const& p2)
|
||||
{
|
||||
return vfs::String::equal(_path.c_str(), p2._path.c_str());
|
||||
}
|
||||
|
||||
bool operator==(vfs::Path const& p1, vfs::Path const& p2)
|
||||
{
|
||||
return vfs::StrCmp::Equal(p1.c_str(), p2.c_str());
|
||||
}
|
||||
bool operator==(vfs::Path const& p1, vfs::String const& p2)
|
||||
{
|
||||
return vfs::StrCmp::Equal(p1.c_str(), p2);
|
||||
}
|
||||
bool operator==(vfs::Path const& p1, vfs::String::str_t const& p2)
|
||||
{
|
||||
return vfs::StrCmp::Equal(p1.c_str(), p2);
|
||||
}
|
||||
bool operator==(vfs::Path const& p1, const vfs::String::char_t* p2)
|
||||
{
|
||||
return vfs::StrCmp::Equal(p1.c_str(), p2);
|
||||
}
|
||||
|
||||
template<>
|
||||
BuildString& BuildString::add<vfs::Path>(vfs::Path const& value)
|
||||
{
|
||||
this->add(value.c_str());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<>
|
||||
BuildString& BuildString::operator<< <vfs::Path>(vfs::Path const& value)
|
||||
{
|
||||
this->add(value.c_str());
|
||||
return *this;
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_profile.cpp
|
||||
* - Virtual Profile, container for real file system locations or archives
|
||||
* - Profile Stack, orders profiles in a linear fashion (top-bottom)
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_profile.h>
|
||||
#include <vfs/Core/vfs.h>
|
||||
#include <vfs/Core/Location/vfs_lib_dir.h>
|
||||
#include <vfs/Core/Location/vfs_directory_tree.h>
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
#include <vfs/Tools/vfs_parser_tools.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
class vfs::CVirtualProfile::IterImpl : public vfs::CVirtualProfile::Iterator::IImplementation
|
||||
{
|
||||
friend class vfs::CVirtualProfile;
|
||||
typedef vfs::CVirtualProfile::Iterator::IImplementation tBaseClass;
|
||||
|
||||
IterImpl(CVirtualProfile* profile) : tBaseClass(), m_profile(profile)
|
||||
{
|
||||
VFS_THROW_IFF(profile, L"");
|
||||
// only unique locations
|
||||
_loc_iter = m_profile->m_setLocations.begin();
|
||||
}
|
||||
public:
|
||||
IterImpl() : tBaseClass(), m_profile(NULL)
|
||||
{};
|
||||
virtual ~IterImpl()
|
||||
{};
|
||||
//////
|
||||
virtual vfs::IBaseLocation* value()
|
||||
{
|
||||
if(_loc_iter != m_profile->m_setLocations.end())
|
||||
{
|
||||
return *_loc_iter;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void next()
|
||||
{
|
||||
if(_loc_iter != m_profile->m_setLocations.end())
|
||||
{
|
||||
_loc_iter++;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl();
|
||||
iter->m_profile = m_profile;
|
||||
iter->_loc_iter = _loc_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
vfs::CVirtualProfile* m_profile;
|
||||
vfs::CVirtualProfile::tUniqueLoc::iterator _loc_iter;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
class vfs::CVirtualProfile::FileIterImpl : public vfs::CVirtualProfile::FileIterator::IImplementation
|
||||
{
|
||||
friend class vfs::CVirtualProfile;
|
||||
typedef vfs::CVirtualProfile::FileIterator::IImplementation tBaseClass;
|
||||
FileIterImpl(vfs::Path const& sPattern, CVirtualProfile* profile);
|
||||
|
||||
public:
|
||||
FileIterImpl() : tBaseClass(), m_profile(NULL)
|
||||
{};
|
||||
virtual ~FileIterImpl()
|
||||
{};
|
||||
/////
|
||||
virtual vfs::IBaseFile* value()
|
||||
{
|
||||
return file;
|
||||
}
|
||||
virtual void next();
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
FileIterImpl* iter2 = new FileIterImpl();
|
||||
iter2->m_pattern = m_pattern;
|
||||
iter2->m_profile = m_profile;
|
||||
iter2->iter = iter;
|
||||
iter2->fiter = fiter;
|
||||
iter2->file = file;
|
||||
return iter2;
|
||||
}
|
||||
private:
|
||||
vfs::Path m_pattern;
|
||||
vfs::CVirtualProfile* m_profile;
|
||||
vfs::CVirtualProfile::Iterator iter;
|
||||
vfs::IBaseLocation::Iterator fiter;
|
||||
vfs::IBaseFile* file;
|
||||
};
|
||||
|
||||
vfs::CVirtualProfile::FileIterImpl::FileIterImpl(vfs::Path const& sPattern, CVirtualProfile* profile)
|
||||
: tBaseClass(), m_pattern(sPattern), m_profile(profile)
|
||||
{
|
||||
VFS_THROW_IFF(profile, L"");
|
||||
iter = m_profile->begin();
|
||||
while(!iter.end())
|
||||
{
|
||||
fiter = iter.value()->begin();
|
||||
while(!fiter.end())
|
||||
{
|
||||
file = fiter.value();
|
||||
if( matchPattern(m_pattern(), file->getPath()()) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
fiter.next();
|
||||
}
|
||||
iter.next();
|
||||
}
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
void vfs::CVirtualProfile::FileIterImpl::next()
|
||||
{
|
||||
if(!fiter.end())
|
||||
{
|
||||
fiter.next();
|
||||
}
|
||||
while(!iter.end())
|
||||
{
|
||||
while(!fiter.end())
|
||||
{
|
||||
file = fiter.value();
|
||||
if( matchPattern(m_pattern(), file->getPath()()) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
fiter.next();
|
||||
}
|
||||
iter.next();
|
||||
if(!iter.end())
|
||||
{
|
||||
fiter = iter.value()->begin();
|
||||
}
|
||||
}
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
vfs::CVirtualProfile::CVirtualProfile(vfs::String const& profile_name, vfs::Path profile_root, bool writable)
|
||||
: cName(profile_name), cRoot(profile_root), cWritable(writable)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CVirtualProfile::~CVirtualProfile()
|
||||
{
|
||||
tUniqueLoc::iterator it = m_setLocations.begin();
|
||||
for(; it != m_setLocations.end(); ++it)
|
||||
{
|
||||
delete (*it);
|
||||
//(*it) = NULL;
|
||||
}
|
||||
m_setLocations.clear();
|
||||
m_mapLocations.clear();
|
||||
};
|
||||
|
||||
vfs::CVirtualProfile::Iterator vfs::CVirtualProfile::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(this));
|
||||
}
|
||||
|
||||
vfs::CVirtualProfile::FileIterator vfs::CVirtualProfile::files(vfs::Path const& sPattern)
|
||||
{
|
||||
return FileIterator( new FileIterImpl(sPattern, this));
|
||||
}
|
||||
|
||||
void vfs::CVirtualProfile::addLocation(vfs::IBaseLocation* pLoc)
|
||||
{
|
||||
if(pLoc)
|
||||
{
|
||||
m_setLocations.insert(pLoc);
|
||||
std::list<vfs::Path> lDirs;
|
||||
pLoc->getSubDirList(lDirs);
|
||||
std::list<vfs::Path>::const_iterator cit = lDirs.begin();
|
||||
for(;cit != lDirs.end(); ++cit)
|
||||
{
|
||||
vfs::IBaseLocation *pOldLoc = m_mapLocations[*cit];
|
||||
if(!pOldLoc)
|
||||
{
|
||||
m_mapLocations[*cit] = pLoc;
|
||||
}
|
||||
else if(pOldLoc == pLoc)
|
||||
{
|
||||
// seems to be an update. do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_LOG_WARNING((L"Another location is already mapped to '" + ((*cit)()) + L"' [keeping old location]").c_str());
|
||||
//VFS_THROW(L"Location already taken");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vfs::IBaseLocation* vfs::CVirtualProfile::getLocation(vfs::Path const& sPath) const
|
||||
{
|
||||
tLocations::const_iterator it = m_mapLocations.find(sPath);
|
||||
if(it != m_mapLocations.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CVirtualProfile::getFile(vfs::Path const& sPath) const
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
sPath.splitLast(sDir,sFile);
|
||||
tLocations::const_iterator it = m_mapLocations.find(sDir);
|
||||
if(it != m_mapLocations.end())
|
||||
{
|
||||
return it->second->getFile(sPath);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
|
||||
class vfs::CProfileStack::IterImpl : public vfs::CProfileStack::Iterator::IImplementation
|
||||
{
|
||||
friend class CProfileStack;
|
||||
typedef CProfileStack::Iterator::IImplementation tBaseClass;
|
||||
|
||||
IterImpl(CProfileStack* pPStack) : tBaseClass(), m_pPStack(pPStack)
|
||||
{
|
||||
VFS_THROW_IFF(m_pPStack, L"");
|
||||
_prof_iter = m_pPStack->m_profiles.begin();
|
||||
}
|
||||
public:
|
||||
IterImpl() : tBaseClass(), m_pPStack(NULL)
|
||||
{};
|
||||
~IterImpl()
|
||||
{};
|
||||
//////
|
||||
virtual vfs::CVirtualProfile* value()
|
||||
{
|
||||
if(_prof_iter != m_pPStack->m_profiles.end())
|
||||
{
|
||||
return *_prof_iter;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void next()
|
||||
{
|
||||
if(_prof_iter != m_pPStack->m_profiles.end())
|
||||
{
|
||||
_prof_iter++;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
IterImpl* iter = new IterImpl();
|
||||
iter->m_pPStack = m_pPStack;
|
||||
iter->_prof_iter = _prof_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
vfs::CProfileStack* m_pPStack;
|
||||
std::list<vfs::CVirtualProfile*>::iterator _prof_iter;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
vfs::CProfileStack::CProfileStack()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CProfileStack::~CProfileStack()
|
||||
{
|
||||
t_profiles::iterator it = m_profiles.begin();
|
||||
for(; it != m_profiles.end(); ++it)
|
||||
{
|
||||
delete (*it);
|
||||
(*it) = NULL;
|
||||
}
|
||||
m_profiles.clear();
|
||||
}
|
||||
|
||||
vfs::CVirtualProfile* vfs::CProfileStack::getProfile(vfs::String const& sName) const
|
||||
{
|
||||
t_profiles::const_iterator it = m_profiles.begin();
|
||||
for(;it != m_profiles.end(); ++it)
|
||||
{
|
||||
if( StrCmp::EqualCase((*it)->cName, sName) )
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs::CVirtualProfile* vfs::CProfileStack::getWriteProfile()
|
||||
{
|
||||
t_profiles::const_iterator it = m_profiles.begin();
|
||||
for(;it != m_profiles.end(); ++it)
|
||||
{
|
||||
if((*it)->cWritable)
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs::CVirtualProfile* vfs::CProfileStack::topProfile() const
|
||||
{
|
||||
if(!m_profiles.empty())
|
||||
{
|
||||
return m_profiles.front();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CProfileStack::popProfile()
|
||||
{
|
||||
// there might be some files in this profile that are referenced in a Log object
|
||||
// we need to it to release the file
|
||||
vfs::Log::flushReleaseAll();
|
||||
// an observer pattern would probably be the better solution,
|
||||
// but for now lets do it this way
|
||||
|
||||
vfs::CVirtualProfile* prof = this->topProfile();
|
||||
if(prof)
|
||||
{
|
||||
vfs::CVirtualProfile::Iterator loc_it = prof->begin();
|
||||
for(; !loc_it.end(); loc_it.next())
|
||||
{
|
||||
vfs::IBaseLocation* loc = loc_it.value();
|
||||
vfs::IBaseLocation::Iterator f_it = loc->begin();
|
||||
for(; !f_it.end(); f_it.next())
|
||||
{
|
||||
vfs::IBaseFile* file = f_it.value();
|
||||
vfs::Path sDir, sFile;
|
||||
if(file)
|
||||
{
|
||||
file->getPath().splitLast(sDir,sFile);
|
||||
vfs::CVirtualLocation* vloc = getVFS()->getVirtualLocation(sDir);
|
||||
if(vloc)
|
||||
{
|
||||
if( !vloc->removeFile(file) )
|
||||
{
|
||||
VFS_THROW(_BS(L"Could not remove file [") << file->getPath()
|
||||
<< L"] in Profile [" << prof->cName << L"]" << _BS::wget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(_BS(L"Virtual location [") << sDir
|
||||
<< L"] doesn't exist. Maybe the VFS was not properly setup." << _BS::wget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(_BS(L"File is NULL during iteration over files in location [")
|
||||
<< loc->getPath() << L"]" << _BS::wget);
|
||||
}
|
||||
}
|
||||
}
|
||||
// delete only when nothing went wrong
|
||||
this->m_profiles.pop_front();
|
||||
delete prof;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void vfs::CProfileStack::pushProfile(CVirtualProfile* pProfile)
|
||||
{
|
||||
if(!getProfile(pProfile->cName))
|
||||
{
|
||||
if(pProfile->cWritable)
|
||||
{
|
||||
m_profiles.push_front(pProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
t_profiles::iterator pit = m_profiles.begin();
|
||||
while(pit != m_profiles.end() && (*pit)->cWritable)
|
||||
{
|
||||
pit++;
|
||||
}
|
||||
//if(pit != m_profiles.end())
|
||||
{
|
||||
m_profiles.insert(pit,pProfile);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// m_profiles.push_front(pProfile);
|
||||
//}
|
||||
}
|
||||
return;
|
||||
}
|
||||
VFS_THROW(L"A profile with this name already exists");
|
||||
}
|
||||
|
||||
vfs::CProfileStack::Iterator vfs::CProfileStack::begin()
|
||||
{
|
||||
return Iterator(new IterImpl(this));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_string.cpp
|
||||
* - string class that allows conversions to/from Unicode representation (uses wchar_t internally)
|
||||
* - comparison, concatenation, stream output class/functions
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_string.h>
|
||||
#include <utf8.h>
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace _StrCmp
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
static inline void Advance( const char*& s1, const char*& s2 )
|
||||
{
|
||||
while (*s1 && *s2 && toupper(*s1) == toupper(*s2))
|
||||
{
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
}
|
||||
static inline void Advance( const wchar_t*& s1, const wchar_t*& s2 )
|
||||
{
|
||||
// should be 'towupper'
|
||||
while (*s1 && *s2 && toupper(*s1) == toupper(*s2))
|
||||
{
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
}
|
||||
template<typename CharType>
|
||||
static inline void AdvanceCase( const CharType*& s1, const CharType*& s2 )
|
||||
{
|
||||
while (*s1 && *s2 && (*s1 == *s2))
|
||||
{
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////
|
||||
template<typename CharType>
|
||||
static inline bool Equal( const CharType* s1, const CharType* s2 )
|
||||
{
|
||||
return !(*s1 || *s2);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////
|
||||
static inline bool Less( const wchar_t* s1, const wchar_t* s2 )
|
||||
{
|
||||
if (!*s1) return *s2 != 0;
|
||||
if (!*s2) return false;
|
||||
// should be 'towupper'
|
||||
return toupper(*s1) < toupper(*s2);
|
||||
}
|
||||
static inline bool Less( const char* s1, const char* s2 )
|
||||
{
|
||||
if (!*s1) return *s2 != 0;
|
||||
if (!*s2) return false;
|
||||
return toupper(*s1) < toupper(*s2);
|
||||
}
|
||||
template<typename CharType>
|
||||
static inline bool LessCase( const CharType* s1, const CharType* s2 )
|
||||
{
|
||||
if (!*s1) return *s2 != 0;
|
||||
if (!*s2) return false;
|
||||
return (*s1) < (*s2);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool vfs::String::lessCase(const vfs::String::char_t* s1, const vfs::String::char_t* s2)
|
||||
{
|
||||
_StrCmp::AdvanceCase(s1,s2);
|
||||
return _StrCmp::LessCase(s1,s2);
|
||||
|
||||
}
|
||||
|
||||
bool vfs::String::less(const vfs::String::char_t* s1, const vfs::String::char_t* s2)
|
||||
{
|
||||
_StrCmp::Advance(s1,s2);
|
||||
return _StrCmp::Less(s1,s2);
|
||||
}
|
||||
|
||||
bool vfs::String::equalCase(const vfs::String::char_t* s1, const vfs::String::char_t* s2)
|
||||
{
|
||||
_StrCmp::AdvanceCase(s1,s2);
|
||||
return _StrCmp::Equal(s1,s2);
|
||||
}
|
||||
|
||||
bool vfs::String::equal(const vfs::String::char_t* s1, const vfs::String::char_t* s2)
|
||||
{
|
||||
_StrCmp::Advance(s1,s2);
|
||||
return _StrCmp::Equal(s1,s2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
/// class constructors
|
||||
////////////////////////////////////////////////////////////////////
|
||||
vfs::String::String()
|
||||
{
|
||||
}
|
||||
vfs::String::String(const char* str)
|
||||
{
|
||||
vfs::String::as_utf16(str,_str);
|
||||
}
|
||||
vfs::String::String(std::string const& str)
|
||||
{
|
||||
vfs::String::as_utf16(str,_str);
|
||||
}
|
||||
vfs::String::String(const wchar_t* str)
|
||||
{
|
||||
_str.assign(str);
|
||||
}
|
||||
vfs::String::String(std::wstring const& str)
|
||||
{
|
||||
_str.assign(str);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
/// static class methods
|
||||
////////////////////////////////////////////////////////////////////
|
||||
vfs::String::str_t vfs::String::as_utf16(std::string const& str)
|
||||
{
|
||||
vfs::String::str_t s;
|
||||
vfs::String::as_utf16(str, s);
|
||||
return s;
|
||||
}
|
||||
void vfs::String::as_utf16(std::string const& str, vfs::String::str_t &str16)
|
||||
{
|
||||
try
|
||||
{
|
||||
::size_t d = utf8::distance(str.begin(), str.end());
|
||||
if(d > 0)
|
||||
{
|
||||
str16.resize(d);
|
||||
utf8::utf8to16(str.begin(), str.end(), &str16[0]);
|
||||
}
|
||||
}
|
||||
catch(utf8::invalid_utf8& ex)
|
||||
{
|
||||
utf8::uint8_t c = ex.utf8_octet();
|
||||
VFS_THROW( _BS(L"Invalid UTF8 character '") << (wchar_t)c << L"'=" << (unsigned char)c <<_BS::wget );
|
||||
}
|
||||
catch(utf8::not_enough_room &ex)
|
||||
{
|
||||
std::wstring err;
|
||||
VFS_IGNOREEXCEPTION(vfs::String::as_utf16(ex.what(),err), true);
|
||||
VFS_THROW( _BS(L"Incomplete UTF8 string [") << err << L"]" << _BS::wget );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
VFS_THROW(L"Unicode error");
|
||||
}
|
||||
}
|
||||
|
||||
vfs::String::str_t vfs::String::as_utf16(const char* str)
|
||||
{
|
||||
vfs::String::str_t s;
|
||||
vfs::String::as_utf16(str, s);
|
||||
return s;
|
||||
}
|
||||
void vfs::String::as_utf16(const char* str, vfs::String::str_t &str16)
|
||||
{
|
||||
if(str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
::size_t len = strlen(str);
|
||||
::size_t d = utf8::distance(str,str+len);
|
||||
if(d > 0)
|
||||
{
|
||||
str16.resize(d);
|
||||
utf8::utf8to16(str, str+len, &str16[0]);
|
||||
}
|
||||
}
|
||||
catch(utf8::invalid_utf8& ex)
|
||||
{
|
||||
utf8::uint8_t c = ex.utf8_octet();
|
||||
VFS_THROW( _BS(L"Invalid UTF8 character '") << (wchar_t)c << L"'=" << (unsigned char)c << _BS::wget );
|
||||
}
|
||||
catch(utf8::not_enough_room &ex)
|
||||
{
|
||||
std::wstring err;
|
||||
VFS_IGNOREEXCEPTION(vfs::String::as_utf16(ex.what(), err), true);
|
||||
VFS_THROW( _BS(L"Incomplete UTF8 string [") << err << L"]" << _BS::wget );
|
||||
}
|
||||
}
|
||||
|
||||
std::string vfs::String::as_utf8(vfs::String const& str)
|
||||
{
|
||||
return str.utf8();
|
||||
}
|
||||
std::string vfs::String::as_utf8(std::wstring const& str)
|
||||
{
|
||||
if(str.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#if 0
|
||||
std::string s;
|
||||
utf8::utf16to8(str.begin(), str.end(), std::back_inserter(s));
|
||||
#else
|
||||
const int UTF8_MAX_CHARS = 4;
|
||||
std::vector<char> buffer(str.length()+UTF8_MAX_CHARS);
|
||||
::size_t pos_in=0, pos_out=0;
|
||||
while(pos_in < str.length())
|
||||
{
|
||||
if( (pos_out+UTF8_MAX_CHARS) >= buffer.size() )
|
||||
{
|
||||
buffer.resize(buffer.size()+str.length());
|
||||
}
|
||||
pos_out = utf8::append(str.at(pos_in++), &buffer[pos_out]) - &buffer[0];
|
||||
}
|
||||
std::string s(&buffer[0],pos_out);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
// if 'strlength' is 0, length is determined automatically
|
||||
std::string vfs::String::as_utf8(const wchar_t* str, vfs::String::size_t strlength)
|
||||
{
|
||||
std::string s;
|
||||
if(str != NULL)
|
||||
{
|
||||
::size_t len = strlength;
|
||||
if(len == 0)
|
||||
{
|
||||
len = wcslen(str);
|
||||
}
|
||||
if(len != 0)
|
||||
{
|
||||
utf8::utf16to8(str,str+len,std::back_inserter(s));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// convenience method, for the case it should be used in generic code (overloading)
|
||||
std::string vfs::String::as_utf8(std::string const& str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
vfs::String::size_t vfs::String::narrow(std::wstring const& src, std::string& dst)
|
||||
{
|
||||
vfs::String::size_t len = vfs::String::narrow(src.c_str(),src.length(),NULL,0);
|
||||
if(len > 0)
|
||||
{
|
||||
dst.resize(len);
|
||||
return vfs::String::narrow(src.c_str(),src.length(),&dst[0],len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
std::string vfs::String::narrow(wchar_t const* str, vfs::String::size_t length)
|
||||
{
|
||||
std::string s;
|
||||
vfs::String::size_t len = vfs::String::narrow(str,length,NULL,0);
|
||||
if(len > 0)
|
||||
{
|
||||
s.resize(len);
|
||||
vfs::String::narrow(str,length,&s[0],len);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
vfs::String::size_t vfs::String::narrow(wchar_t const* src_str, vfs::String::size_t src_len, char* dst_str, vfs::String::size_t dst_len)
|
||||
{
|
||||
if(src_str && src_len>0)
|
||||
{
|
||||
if(!dst_str || dst_len==0)
|
||||
{
|
||||
return wcstombs(NULL, src_str, src_len);
|
||||
}
|
||||
return wcstombs(dst_str, src_str, std::min<vfs::String::size_t>(src_len,dst_len));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
std::wstring vfs::String::widen(char const* str, vfs::String::size_t length)
|
||||
{
|
||||
std::wstring ws;
|
||||
vfs::String::size_t len = vfs::String::widen(str,length,NULL,0);
|
||||
if(len > 0)
|
||||
{
|
||||
ws.resize(len);
|
||||
vfs::String::widen(str,length,&ws[0],len);
|
||||
}
|
||||
return ws;
|
||||
}
|
||||
vfs::String::size_t vfs::String::widen(std::string const& src, std::wstring& dst)
|
||||
{
|
||||
vfs::String::size_t len = vfs::String::widen(src.c_str(),src.length(),NULL,0);
|
||||
if(len > 0)
|
||||
{
|
||||
dst.resize(len);
|
||||
return vfs::String::widen(src.c_str(),src.length(),&dst[0],len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
vfs::String::size_t vfs::String::widen(char const* src_str, size_t src_len, wchar_t* dst_str, size_t dst_len)
|
||||
{
|
||||
if(src_str && src_len>0)
|
||||
{
|
||||
if(!dst_str || dst_len==0)
|
||||
{
|
||||
return mbstowcs(NULL, src_str, src_len);
|
||||
}
|
||||
return mbstowcs(dst_str, src_str, std::min<size_t>(src_len,dst_len));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool vfs::String::empty() const
|
||||
{
|
||||
return _str.empty();
|
||||
}
|
||||
vfs::String::size_t vfs::String::length() const
|
||||
{
|
||||
return _str.length();
|
||||
}
|
||||
|
||||
vfs::String vfs::String::operator+(vfs::String const& str)
|
||||
{
|
||||
return vfs::String(_str + str._str);
|
||||
}
|
||||
vfs::String vfs::String::operator+=(vfs::String const& str)
|
||||
{
|
||||
_str += str._str;
|
||||
return vfs::String(_str);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
bool vfs::operator<(vfs::String const& s1, vfs::String const& s2)
|
||||
{
|
||||
return s1._str < s2._str;
|
||||
}
|
||||
|
||||
std::wostream& operator<<(std::wostream& out, vfs::String const& str)
|
||||
{
|
||||
out.write(str.c_str(), (std::streamsize)str.length());
|
||||
return out;
|
||||
}
|
||||
|
||||
std::wostream& operator<<(std::wostream& out, vfs::String::str_t const& str)
|
||||
{
|
||||
out.write(str.c_str(), (std::streamsize)str.length());
|
||||
return out;
|
||||
}
|
||||
|
||||
std::wostream& operator<<(std::wostream& out, const vfs::String::char_t* str)
|
||||
{
|
||||
out.write(str, (std::streamsize)wcslen(str));
|
||||
return out;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
// case IN-sensitive
|
||||
bool vfs::StrCmp::Equal(const char* s1, const char* s2)
|
||||
{
|
||||
_StrCmp::Advance(s1,s2);
|
||||
return _StrCmp::Equal(s1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(std::string const& s1, std::string const& s2)
|
||||
{
|
||||
const char* p1 = s1.c_str();
|
||||
const char* p2 = s2.c_str();
|
||||
_StrCmp::Advance(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(std::string const& s1, const char* s2)
|
||||
{
|
||||
const char* p1 = s1.c_str();
|
||||
_StrCmp::Advance(p1,s2);
|
||||
return _StrCmp::Equal(p1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(const char* s1, std::string const& s2)
|
||||
{
|
||||
const char* p2 = s2.c_str();
|
||||
_StrCmp::Advance(s1,p2);
|
||||
return _StrCmp::Equal(s1,p2);
|
||||
}
|
||||
//
|
||||
bool vfs::StrCmp::Equal(const wchar_t* s1, const wchar_t* s2)
|
||||
{
|
||||
_StrCmp::Advance(s1,s2);
|
||||
return _StrCmp::Equal(s1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(std::wstring const& s1, std::wstring const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::Advance(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(std::wstring const& s1, const wchar_t* s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
_StrCmp::Advance(p1,s2);
|
||||
return _StrCmp::Equal(p1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(const wchar_t* s1, std::wstring const& s2)
|
||||
{
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::Advance(s1,p2);
|
||||
return _StrCmp::Equal(s1,p2);
|
||||
}
|
||||
//
|
||||
bool vfs::StrCmp::Equal(vfs::String const& s1, vfs::String const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::Advance(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(vfs::String const& s1, std::wstring const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::Advance(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(std::wstring const& s1, vfs::String const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::Advance(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(vfs::String const& s1, const wchar_t* s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
_StrCmp::Advance(p1,s2);
|
||||
return _StrCmp::Equal(p1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::Equal(const wchar_t* s1, vfs::String const& s2)
|
||||
{
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::Advance(s1,p2);
|
||||
return _StrCmp::Equal(s1,p2);
|
||||
}
|
||||
// case Sensitive
|
||||
bool vfs::StrCmp::EqualCase(const char* s1, const char* s2)
|
||||
{
|
||||
_StrCmp::AdvanceCase(s1,s2);
|
||||
return _StrCmp::Equal(s1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(std::string const& s1, std::string const& s2)
|
||||
{
|
||||
const char* p1 = s1.c_str();
|
||||
const char* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(std::string const& s1, const char* s2)
|
||||
{
|
||||
const char* p1 = s1.c_str();
|
||||
_StrCmp::AdvanceCase(p1,s2);
|
||||
return _StrCmp::Equal(p1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(const char* s1, std::string const& s2)
|
||||
{
|
||||
const char* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(s1,p2);
|
||||
return _StrCmp::Equal(s1,p2);
|
||||
}
|
||||
//
|
||||
bool vfs::StrCmp::EqualCase(const wchar_t* s1, const wchar_t* s2)
|
||||
{
|
||||
_StrCmp::AdvanceCase(s1,s2);
|
||||
return _StrCmp::Equal(s1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(std::wstring const& s1, std::wstring const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(std::wstring const& s1, const wchar_t* s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
_StrCmp::AdvanceCase(p1,s2);
|
||||
return _StrCmp::Equal(p1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(const wchar_t* s1, std::wstring const& s2)
|
||||
{
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(s1,p2);
|
||||
return _StrCmp::Equal(s1,p2);
|
||||
}
|
||||
//
|
||||
bool vfs::StrCmp::EqualCase(vfs::String const& s1, vfs::String const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(vfs::String const& s1, std::wstring const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(std::wstring const& s1, vfs::String const& s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(p1,p2);
|
||||
return _StrCmp::Equal(p1,p2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(vfs::String const& s1, const wchar_t* s2)
|
||||
{
|
||||
const wchar_t* p1 = s1.c_str();
|
||||
_StrCmp::AdvanceCase(p1,s2);
|
||||
return _StrCmp::Equal(p1,s2);
|
||||
}
|
||||
bool vfs::StrCmp::EqualCase(const wchar_t* s1, vfs::String const& s2)
|
||||
{
|
||||
const wchar_t* p2 = s2.c_str();
|
||||
_StrCmp::AdvanceCase(s1,p2);
|
||||
return _StrCmp::Equal(s1,p2);
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
template<>
|
||||
BuildString& BuildString::add<vfs::String>(vfs::String const& value)
|
||||
{
|
||||
this->add(value.c_str());
|
||||
return *this;
|
||||
}
|
||||
template<>
|
||||
BuildString& BuildString::add<std::string>(std::string const& value)
|
||||
{
|
||||
this->add(vfs::String::as_utf16(value));
|
||||
return *this;
|
||||
}
|
||||
template<>
|
||||
BuildString& BuildString::add<const char*>(const char* const& value)
|
||||
{
|
||||
this->add(vfs::String::as_utf16(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<>
|
||||
BuildString& BuildString::operator<< <vfs::String>(vfs::String const& value)
|
||||
{
|
||||
this->add(value.c_str());
|
||||
return *this;
|
||||
}
|
||||
template<>
|
||||
BuildString& BuildString::operator<< <std::string>(std::string const& value)
|
||||
{
|
||||
this->add(vfs::String::as_utf16(value));
|
||||
return *this;
|
||||
}
|
||||
template<>
|
||||
BuildString& BuildString::operator<< <const char*>(const char* const& value)
|
||||
{
|
||||
this->add(vfs::String::as_utf16(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_types.cpp
|
||||
* - basic integer types, "incomplete" list of useful constant strings
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_types.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
const vfs::size_t npos = vfs::size_t(-1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_vfile.cpp
|
||||
* - Virtual File, handles access to files from different VFS profiles
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_vfile.h>
|
||||
#include <vfs/Core/vfs_vloc.h>
|
||||
#include <vfs/Core/vfs.h>
|
||||
|
||||
// static member
|
||||
vfs::ObjBlockAllocator<vfs::CVirtualFile>* vfs::CVirtualFile::_vfile_pool = NULL;
|
||||
|
||||
vfs::CVirtualFile* vfs::CVirtualFile::create(vfs::Path const& sFilePath, vfs::CProfileStack& rPStack)
|
||||
{
|
||||
unsigned int ID=0;
|
||||
#ifdef VFILE_BLOCK_CREATE
|
||||
if(!_vfile_pool)
|
||||
{
|
||||
_vfile_pool = new ObjBlockAllocator<vfs::CVirtualFile>();
|
||||
vfs::ObjectAllocator::registerAllocator(_vfile_pool);
|
||||
}
|
||||
CVirtualFile* file = _vfile_pool->New(&ID);
|
||||
#else
|
||||
CVirtualFile* file = new CVirtualFile();
|
||||
#endif
|
||||
file->_path = sFilePath;
|
||||
file->_pstack = &rPStack;
|
||||
file->_myID = ID;
|
||||
return file;
|
||||
}
|
||||
|
||||
void vfs::CVirtualFile::destroy()
|
||||
{
|
||||
#ifndef VFILE_BLOCK_CREATE
|
||||
delete this;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
vfs::CVirtualFile::CVirtualFile()
|
||||
: _path(L""), _top_pname(L"_INVALID_"), _top_file(NULL), _pstack(NULL), _myID(vfs::UInt32(-1))
|
||||
{
|
||||
};
|
||||
|
||||
vfs::CVirtualFile::~CVirtualFile()
|
||||
{
|
||||
}
|
||||
|
||||
vfs::Path const& vfs::CVirtualFile::path()
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
void vfs::CVirtualFile::add(vfs::IBaseFile *pFile, vfs::String sProfileName, bool bReplace)
|
||||
{
|
||||
if(pFile)
|
||||
{
|
||||
// if there is no file then just set it
|
||||
// if bReplace is set to true then override all other settings and just set the file
|
||||
if(!_top_file || bReplace)
|
||||
{
|
||||
_top_file = pFile;
|
||||
_top_pname = sProfileName;
|
||||
return;
|
||||
}
|
||||
// file already set, but new file is? the same object
|
||||
if(pFile == _top_file)
|
||||
{
|
||||
VFS_THROW_IFF( StrCmp::Equal(sProfileName,_top_pname), L"same file, different profile name");
|
||||
}
|
||||
// OK, not the same file, but these two different files are supposed to have the same filename
|
||||
VFS_THROW_IFF( _top_file->getName() == pFile->getName(), L"different filenames");
|
||||
// set new file only when its profile is on top of the current file's profile
|
||||
bool bFoundOld = false, bFoundNew = false;
|
||||
vfs::CProfileStack::Iterator it = _pstack->begin();
|
||||
for(; !it.end(); it.next())
|
||||
{
|
||||
if(_top_pname == it.value()->cName)
|
||||
{
|
||||
bFoundOld = true;
|
||||
break;
|
||||
}
|
||||
else if(sProfileName == it.value()->cName)
|
||||
{
|
||||
bFoundNew = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(bFoundNew && !bFoundOld)
|
||||
{
|
||||
_top_file = pFile;
|
||||
_top_pname = sProfileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns : returns true if pFile is not top file or top file could be replaced with another file
|
||||
* returns false if there is no more files with given name. in this case object should be destroyed
|
||||
*/
|
||||
bool vfs::CVirtualFile::remove(vfs::IBaseFile *pFile)
|
||||
{
|
||||
if(_top_file == pFile)
|
||||
{
|
||||
if(_path == pFile->getPath())
|
||||
{
|
||||
// need to replace '_top_file'
|
||||
vfs::CProfileStack::Iterator prof_it = _pstack->begin();
|
||||
for(; !prof_it.end(); prof_it.next())
|
||||
{
|
||||
CVirtualProfile *pProf = prof_it.value();
|
||||
if(pProf)
|
||||
{
|
||||
vfs::IBaseFile *file = pProf->getFile(_path);
|
||||
if(file && (file != pFile))
|
||||
{
|
||||
_top_file = file;
|
||||
_top_pname = pProf->cName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// no more files
|
||||
_top_file = NULL;
|
||||
_top_pname = "";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_THROW(L"Same file object but different file paths? WTH?");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CVirtualFile::file(ESearchFile eSearch)
|
||||
{
|
||||
if(eSearch == SF_TOP)
|
||||
{
|
||||
return _top_file;
|
||||
}
|
||||
else if(eSearch == SF_FIRST_WRITABLE)
|
||||
{
|
||||
CVirtualProfile *pVProf = _pstack->getWriteProfile();
|
||||
if(pVProf)
|
||||
{
|
||||
return pVProf->getFile(_path);
|
||||
}
|
||||
}
|
||||
else if(eSearch == SF_STOP_ON_WRITABLE_PROFILE)
|
||||
{
|
||||
vfs::CProfileStack::Iterator prof_it = _pstack->begin();
|
||||
for(; !prof_it.end(); prof_it.next())
|
||||
{
|
||||
CVirtualProfile *pProf = prof_it.value();
|
||||
if(pProf)
|
||||
{
|
||||
if(pProf->cWritable)
|
||||
{
|
||||
return pProf->getFile(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
vfs::IBaseFile *pFile = pProf->getFile(_path);
|
||||
if(pFile)
|
||||
{
|
||||
return pFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CVirtualFile::file(vfs::String const& sProfileName)
|
||||
{
|
||||
if(sProfileName == _top_pname)
|
||||
{
|
||||
return vfs::tReadableFile::cast(_top_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
CVirtualProfile* pProf = _pstack->getProfile(sProfileName);
|
||||
if(pProf)
|
||||
{
|
||||
CVirtualProfile::Iterator loc_it = pProf->begin();
|
||||
for(; !loc_it.end(); loc_it.next())
|
||||
{
|
||||
if(loc_it.value() && loc_it.value()->fileExists(_path))
|
||||
{
|
||||
if(loc_it.value())
|
||||
{
|
||||
return loc_it.value()->getFile(_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* bfVFS : vfs/Core/vfs_vloc.cpp
|
||||
* - Virtual Location, stores Virtual Files
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs_vloc.h>
|
||||
#include <vfs/Core/vfs_vfile.h>
|
||||
#include <vfs/Core/vfs_profile.h>
|
||||
#include <vfs/Core/vfs.h>
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
class vfs::CVirtualLocation::VFileIterator : public vfs::CVirtualLocation::Iterator::IImplementation
|
||||
{
|
||||
friend class vfs::CVirtualLocation;
|
||||
typedef vfs::CVirtualLocation::Iterator::IImplementation tBaseClass;
|
||||
|
||||
VFileIterator(vfs::CVirtualLocation* pLoc): tBaseClass(), m_pLoc(pLoc)
|
||||
{
|
||||
VFS_THROW_IFF(pLoc, L"");
|
||||
_vfile_iter = m_pLoc->m_VFiles.begin();
|
||||
}
|
||||
public:
|
||||
VFileIterator() : tBaseClass(), m_pLoc(NULL)
|
||||
{};
|
||||
virtual ~VFileIterator()
|
||||
{};
|
||||
virtual vfs::CVirtualFile* value()
|
||||
{
|
||||
if(m_pLoc && _vfile_iter != m_pLoc->m_VFiles.end())
|
||||
{
|
||||
return _vfile_iter->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
virtual void next()
|
||||
{
|
||||
if(m_pLoc && _vfile_iter != m_pLoc->m_VFiles.end())
|
||||
{
|
||||
_vfile_iter++;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual tBaseClass* clone()
|
||||
{
|
||||
VFileIterator* iter = new VFileIterator(m_pLoc);
|
||||
iter->_vfile_iter = _vfile_iter;
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
vfs::CVirtualLocation* m_pLoc;
|
||||
vfs::CVirtualLocation::tVFiles::iterator _vfile_iter;
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
vfs::CVirtualLocation::CVirtualLocation(vfs::Path const& path)
|
||||
: cPath(path), m_exclusive(false)
|
||||
{};
|
||||
|
||||
vfs::CVirtualLocation::~CVirtualLocation()
|
||||
{
|
||||
tVFiles::iterator it = m_VFiles.begin();
|
||||
for(; it != m_VFiles.end(); ++it)
|
||||
{
|
||||
it->second->destroy();
|
||||
}
|
||||
m_VFiles.clear();
|
||||
}
|
||||
|
||||
void vfs::CVirtualLocation::setIsExclusive(bool exclusive)
|
||||
{
|
||||
m_exclusive = exclusive;
|
||||
}
|
||||
bool vfs::CVirtualLocation::getIsExclusive()
|
||||
{
|
||||
return m_exclusive;
|
||||
}
|
||||
|
||||
void vfs::CVirtualLocation::addFile(vfs::IBaseFile* file, vfs::String const& profileName)
|
||||
{
|
||||
vfs::CVirtualFile *pVFile = NULL;
|
||||
tVFiles::iterator it = m_VFiles.find(file->getName());
|
||||
if(it == m_VFiles.end())
|
||||
{
|
||||
vfs::Path fp = file->getPath();
|
||||
vfs::CProfileStack& stack = *(getVFS()->getProfileStack());
|
||||
pVFile = vfs::CVirtualFile::create(fp,stack);
|
||||
it = m_VFiles.insert(m_VFiles.end(), std::pair<vfs::Path,vfs::CVirtualFile*>(file->getName(),pVFile));
|
||||
}
|
||||
it->second->add(file,profileName,true);
|
||||
}
|
||||
|
||||
vfs::IBaseFile* vfs::CVirtualLocation::getFile(vfs::Path const& filename, vfs::String const& profileName) const
|
||||
{
|
||||
tVFiles::const_iterator cit = m_VFiles.find(filename);
|
||||
if(cit != m_VFiles.end() && cit->second)
|
||||
{
|
||||
if(profileName.empty())
|
||||
{
|
||||
if(m_exclusive)
|
||||
{
|
||||
return cit->second->file(vfs::CVirtualFile::SF_STOP_ON_WRITABLE_PROFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return cit->second->file(vfs::CVirtualFile::SF_TOP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// you know what you are doing
|
||||
return cit->second->file(profileName);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
vfs::CVirtualFile* vfs::CVirtualLocation::getVirtualFile(vfs::Path const& filename)
|
||||
{
|
||||
tVFiles::const_iterator cit = m_VFiles.find(filename);
|
||||
if(cit != m_VFiles.end())
|
||||
{
|
||||
return cit->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool vfs::CVirtualLocation::removeFile(vfs::IBaseFile* file)
|
||||
{
|
||||
if(file)
|
||||
{
|
||||
vfs::Path sDir,sFile;
|
||||
file->getPath().splitLast(sDir,sFile);
|
||||
tVFiles::iterator it = m_VFiles.find(sFile);
|
||||
if(it != m_VFiles.end())
|
||||
{
|
||||
if(!it->second->remove(file))
|
||||
{
|
||||
//CVirtualFile* vfile = it->second;
|
||||
//delete vfile;
|
||||
m_VFiles.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
vfs::CVirtualLocation::Iterator vfs::CVirtualLocation::iterate()
|
||||
{
|
||||
return Iterator(new VFileIterator(this));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* bfVFS : vfs/Ext/7z/vfs_7z_library.cpp
|
||||
* - implements Library interface, creates library object from uncompressed 7-zip archive files
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef VFS_WITH_7ZIP
|
||||
|
||||
#include <vfs/Ext/7z/vfs_7z_library.h>
|
||||
#include <vfs/Core/Location/vfs_lib_dir.h>
|
||||
#include <vfs/Core/File/vfs_lib_file.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
|
||||
namespace sz
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#include <7z.h>
|
||||
#include <7zCrc.h>
|
||||
#include <7zAlloc.h>
|
||||
//#include <Archive/7z/7zAlloc.h>
|
||||
//#include <Archive/7z/7zExtract.h>
|
||||
//#include <Archive/7z/7zIn.h>
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
/*** my 7z extensions ***/
|
||||
/********************************************************************************************/
|
||||
|
||||
namespace szExt
|
||||
{
|
||||
typedef struct CSzVfsFile
|
||||
{
|
||||
vfs::tReadableFile* file;
|
||||
} CSzVfsFile;
|
||||
|
||||
typedef struct CVfsFileInStream
|
||||
{
|
||||
sz::ISeekInStream s;
|
||||
CSzVfsFile file;
|
||||
} CVfsFileInStream;
|
||||
|
||||
|
||||
static sz::SRes VfsFileInStream_Read(void *pp, void *buf, ::size_t *size)
|
||||
{
|
||||
CVfsFileInStream *p = (CVfsFileInStream *)pp;
|
||||
::size_t to_read = *size;
|
||||
sz::SRes res;
|
||||
try
|
||||
{
|
||||
*size = (::size_t)p->file.file->read((vfs::Byte*)buf,to_read);
|
||||
res = SZ_OK;
|
||||
}
|
||||
catch(std::exception &ex)
|
||||
{
|
||||
VFS_LOG_ERROR(ex.what());
|
||||
res = SZ_ERROR_READ;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static sz::SRes VfsFileInStream_Seek(void *pp, sz::Int64 *pos, sz::ESzSeek origin)
|
||||
{
|
||||
CVfsFileInStream *p = (CVfsFileInStream *)pp;
|
||||
|
||||
vfs::IBaseFile::ESeekDir eSD;
|
||||
switch (origin)
|
||||
{
|
||||
case sz::SZ_SEEK_SET:
|
||||
eSD = vfs::IBaseFile::SD_BEGIN;
|
||||
break;
|
||||
case sz::SZ_SEEK_CUR:
|
||||
eSD = vfs::IBaseFile::SD_CURRENT;
|
||||
break;
|
||||
case sz::SZ_SEEK_END:
|
||||
eSD = vfs::IBaseFile::SD_END;
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_PARAM;
|
||||
}
|
||||
vfs::offset_t _pos = (vfs::offset_t)(*pos);
|
||||
sz::SRes res;
|
||||
try
|
||||
{
|
||||
p->file.file->setReadPosition(_pos,eSD);
|
||||
*pos = p->file.file->getReadPosition();
|
||||
res = SZ_OK;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_LOG_ERROR(ex.what());
|
||||
res = SZ_ERROR_READ;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void VfsFileInStream_CreateVTable(CVfsFileInStream *p)
|
||||
{
|
||||
p->s.Read = VfsFileInStream_Read;
|
||||
p->s.Seek = VfsFileInStream_Seek;
|
||||
}
|
||||
}; // end namespace szExt
|
||||
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
vfs::CUncompressed7zLibrary::CUncompressed7zLibrary(
|
||||
tReadableFile *libraryFile,
|
||||
vfs::Path const& mountPoint,
|
||||
bool ownFile,
|
||||
vfs::ObjBlockAllocator<vfs::CLibFile>* allocator)
|
||||
: vfs::CUncompressedLibraryBase(libraryFile, mountPoint, ownFile), _allocator(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
vfs::CUncompressed7zLibrary::~CUncompressed7zLibrary()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#define k_Copy 0
|
||||
|
||||
sz::UInt64 GetSum(const sz::UInt64 *values, sz::UInt32 index)
|
||||
{
|
||||
sz::UInt64 sum = 0;
|
||||
sz::UInt32 i;
|
||||
for (i = 0; i < index; i++)
|
||||
{
|
||||
sum += values[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool vfs::CUncompressed7zLibrary::init()
|
||||
{
|
||||
if(!m_libraryFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
szExt::CVfsFileInStream archiveStream;
|
||||
sz::CLookToRead lookStream;
|
||||
sz::CSzArEx db;
|
||||
sz::SRes res;
|
||||
sz::ISzAlloc allocImp;
|
||||
sz::ISzAlloc allocTempImp;
|
||||
|
||||
vfs::COpenReadFile rfile(m_libraryFile);
|
||||
|
||||
archiveStream.file.file = m_libraryFile;
|
||||
|
||||
szExt::VfsFileInStream_CreateVTable(&archiveStream);
|
||||
sz::LookToRead_CreateVTable(&lookStream, False);
|
||||
|
||||
lookStream.realStream = &archiveStream.s;
|
||||
sz::LookToRead_Init(&lookStream);
|
||||
|
||||
allocImp.Alloc = sz::SzAlloc;
|
||||
allocImp.Free = sz::SzFree;
|
||||
|
||||
allocTempImp.Alloc = sz::SzAllocTemp;
|
||||
allocTempImp.Free = sz::SzFreeTemp;
|
||||
|
||||
sz::CrcGenerateTable();
|
||||
|
||||
sz::SzArEx_Init(&db);
|
||||
if( SZ_OK != (res = sz::SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp)) )
|
||||
{
|
||||
VFS_THROW(_BS(L"Could not open 7z archive [") << m_libraryFile->getPath() << L"]" << _BS::wget);
|
||||
}
|
||||
|
||||
vfs::TDirectory<ILibrary::tWriteType>* pLD = NULL;
|
||||
vfs::Path oDir, oFile;
|
||||
vfs::Path oDirPath;
|
||||
|
||||
const size_t FBUFFER_SIZE = 1024;
|
||||
std::vector<vfs::UInt16> fname_buffer;
|
||||
fname_buffer.resize(FBUFFER_SIZE);
|
||||
for(vfs::UInt32 i = 0; i < db.db.NumFiles; i++)
|
||||
{
|
||||
sz::CSzFileItem *f = db.db.Files + i;
|
||||
if (f->IsDir)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
size_t fsize = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||
if(fsize >= fname_buffer.size())
|
||||
{
|
||||
fname_buffer.resize(fsize + 32);
|
||||
}
|
||||
fsize = SzArEx_GetFileNameUtf16(&db, i, &fname_buffer[0]);
|
||||
fname_buffer[fsize] = 0;
|
||||
vfs::Path sPath((wchar_t*)&fname_buffer[0]);
|
||||
sPath.splitLast(oDir,oFile);
|
||||
oDirPath = m_mountPoint;
|
||||
if(!oDir.empty())
|
||||
{
|
||||
oDirPath += oDir;
|
||||
}
|
||||
|
||||
// determine offset and size
|
||||
sz::UInt32 folderIndex = db.FileIndexToFolderIndexMap[i];
|
||||
|
||||
sz::CSzFolder *folder = db.db.Folders + folderIndex;
|
||||
sz::UInt64 unpackSizeSpec = sz::SzFolder_GetUnpackSize(folder);
|
||||
size_t unpackSize = (size_t)unpackSizeSpec;
|
||||
sz::UInt64 startOffset = sz::SzArEx_GetFolderStreamPos(&db, folderIndex, 0);
|
||||
|
||||
//const sz::UInt64 *packSizes = db.db.PackSizes + db.FolderStartPackStreamIndex[folderIndex];
|
||||
|
||||
//CSzCoderInfo *coder = &folder->Coders[0];
|
||||
//if (coder->MethodID == k_Copy)
|
||||
//{
|
||||
// UInt32 si = 0;
|
||||
// UInt64 offset;
|
||||
// UInt64 inSize;
|
||||
// offset = GetSum(packSizes, si);
|
||||
// inSize = packSizes[si];
|
||||
//}
|
||||
|
||||
// get or create according directory object
|
||||
tDirCatalogue::iterator it = m_dirs.find(oDirPath);
|
||||
if(it != m_dirs.end())
|
||||
{
|
||||
pLD = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLD = new vfs::CLibDirectory(oDir,oDirPath);
|
||||
m_dirs.insert(std::make_pair(oDirPath,pLD));
|
||||
}
|
||||
// create file
|
||||
vfs::CLibFile *pFile = vfs::CLibFile::create(oFile,pLD,this,_allocator);
|
||||
// add file to directory
|
||||
VFS_THROW_IFF( pLD->addFile(pFile), L"" );
|
||||
|
||||
// link file data struct to file object
|
||||
m_fileData.insert(std::make_pair(pFile,SFileData(unpackSize, (vfs::size_t)startOffset)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_LOG_ERROR(ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VFS_WITH_7ZIP
|
||||
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* bfVFS : vfs/Ext/7z/vfs_create_7z_library.cpp
|
||||
* - writes uncompressed 7z archive file
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef VFS_WITH_7ZIP
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <vfs/Core/vfs_types.h>
|
||||
|
||||
#include <vfs/Ext/7z/vfs_create_7z_library.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
|
||||
namespace sz
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#include <7zCrc.h>
|
||||
#include <7z.h>
|
||||
//#include "Archive/7z/7zIn.h"
|
||||
}
|
||||
};
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
namespace szExt
|
||||
{
|
||||
inline ::size_t WRITEBYTE(std::ostream& out, sz::Byte const& value)
|
||||
{
|
||||
out.write((char*)&value,sizeof(sz::Byte));
|
||||
return 1;
|
||||
}
|
||||
template<typename T>
|
||||
inline ::size_t WRITEALL(std::ostream& out, T const& value)
|
||||
{
|
||||
out.write((char*)&value,sizeof(T));
|
||||
return sizeof(T);
|
||||
}
|
||||
template<typename T>
|
||||
inline ::size_t WRITEBUFFER(std::ostream& out, T* value, ::size_t num_elements)
|
||||
{
|
||||
out.write((char*)value, num_elements*sizeof(T));
|
||||
return num_elements*sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* "compress" numbers by removing heading zero-bytes
|
||||
* - add additional byte that represents a bit-vector of bytes within a 64-bit/8-byte number
|
||||
* - if the number is smaller than 128, use the extra byte to store the value
|
||||
*/
|
||||
template<typename T>
|
||||
inline ::size_t WRITE(std::ostream& out, T const& value)
|
||||
{
|
||||
::size_t count = 0;
|
||||
sz::Byte data[8];
|
||||
sz::Byte firstByte = 0;
|
||||
sz::Byte* b = (sz::Byte*)&value;
|
||||
::size_t SIZE = sizeof(T);
|
||||
b+= SIZE-1;
|
||||
vfs::Int32 i;
|
||||
for(i = (vfs::Int32)(SIZE-1); i>=0; --i)
|
||||
{
|
||||
if( (*b & 0xFF) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
b--;
|
||||
}
|
||||
if(i < 0)
|
||||
{
|
||||
count += WRITEBYTE(out,0);
|
||||
return count;
|
||||
}
|
||||
if(i == 0)
|
||||
{
|
||||
if(*b >= 0x80)
|
||||
{
|
||||
count += WRITEBYTE(out,0x80);
|
||||
}
|
||||
count += WRITEBYTE(out,*b);
|
||||
return count;
|
||||
}
|
||||
vfs::Int32 num = 0;
|
||||
for(;i >= 0; --i)
|
||||
{
|
||||
firstByte |= 1 << (8 - i - 1);
|
||||
data[i] = *b--;
|
||||
num++;
|
||||
}
|
||||
count += WRITEBYTE(out,firstByte);
|
||||
count += WRITEBUFFER(out,data,num);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
|
||||
vfs::CCreateUncompressed7zLibrary::CCreateUncompressed7zLibrary()
|
||||
: m_pLibFile(NULL)
|
||||
{
|
||||
sz::CrcGenerateTable();
|
||||
}
|
||||
|
||||
vfs::CCreateUncompressed7zLibrary::~CCreateUncompressed7zLibrary()
|
||||
{
|
||||
m_pLibFile = NULL;
|
||||
|
||||
m_lFileInfo.clear();
|
||||
m_mapDirInfo.clear();
|
||||
}
|
||||
|
||||
bool vfs::CCreateUncompressed7zLibrary::addFile(vfs::tReadableFile* pFile)
|
||||
{
|
||||
if(!pFile)
|
||||
{
|
||||
// at least nothing bad happened
|
||||
return true;
|
||||
}
|
||||
try
|
||||
{
|
||||
vfs::COpenReadFile infile(pFile);
|
||||
}
|
||||
catch(std::exception &ex)
|
||||
{
|
||||
std::wstringstream wss;
|
||||
wss << L"Could not open File \"" << pFile->getPath()() << L"\"";
|
||||
VFS_RETHROW(wss.str().c_str(), ex);
|
||||
}
|
||||
SFileInfo fi;
|
||||
vfs::Path filename = pFile->getPath();
|
||||
fi.name = filename.c_wcs();
|
||||
fi.size = pFile->getSize();
|
||||
if(m_lFileInfo.empty())
|
||||
{
|
||||
fi.offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SFileInfo const& fic = m_lFileInfo.back();
|
||||
fi.offset = fic.offset + fic.size;
|
||||
}
|
||||
|
||||
typedef std::vector<vfs::Byte> tByteVector;
|
||||
tByteVector data( (tByteVector::size_type)fi.size );
|
||||
VFS_THROW_IFF(fi.size == pFile->read(&data[0], (vfs::size_t)fi.size), L"");
|
||||
fi.CRC = sz::CrcCalc(&data[0],(::size_t)fi.size);
|
||||
m_ssFileStream.write(&data[0],(std::streamsize)fi.size);
|
||||
|
||||
m_lFileInfo.push_back(fi);
|
||||
|
||||
vfs::Path path,dummy;
|
||||
filename.splitLast(path,dummy);
|
||||
if(!path.empty())
|
||||
{
|
||||
tDirInfo::iterator it_find = m_mapDirInfo.find(path.c_wcs());
|
||||
if(it_find == m_mapDirInfo.end())
|
||||
{
|
||||
SFileInfo dir;
|
||||
dir.name = path.c_wcs();
|
||||
dir.offset = 0;
|
||||
dir.size = 0;
|
||||
dir.time_creation = 0;
|
||||
dir.time_last_access = 0;
|
||||
dir.time_write = 0;
|
||||
m_mapDirInfo.insert(std::make_pair(dir.name,dir));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeLibrary(vfs::Path const& sLibName)
|
||||
{
|
||||
vfs::COpenWriteFile outfile(sLibName,true);
|
||||
return writeLibrary(&outfile.file());
|
||||
}
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeLibrary(vfs::tWritableFile* pFile)
|
||||
{
|
||||
if(!pFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(m_lFileInfo.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_pLibFile = pFile;
|
||||
if(!m_pLibFile->isOpenWrite() && !m_pLibFile->openWrite(true,true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//
|
||||
writeNextHeader(m_ssInfoStream);
|
||||
//
|
||||
std::stringstream ssSigHeader;
|
||||
writeSignatureHeader(ssSigHeader);
|
||||
//
|
||||
m_pLibFile->write(ssSigHeader.str().c_str() , (vfs::size_t)ssSigHeader.str().length());
|
||||
//
|
||||
m_pLibFile->write(m_ssFileStream.str().c_str() , (vfs::size_t)m_ssFileStream.str().length());
|
||||
//
|
||||
m_pLibFile->write(m_ssInfoStream.str().c_str() , (vfs::size_t)m_ssInfoStream.str().length());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************************/
|
||||
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeSignatureHeader(std::ostream& out)
|
||||
{
|
||||
::size_t count=0;
|
||||
|
||||
// #define k7zSignatureSize -> not in namespace sz
|
||||
count += szExt::WRITEBUFFER(out, sz::k7zSignature, k7zSignatureSize);
|
||||
|
||||
sz::Byte Major = 0, Minor = 2;
|
||||
count += szExt::WRITEALL(out, (sz::Byte)Major );
|
||||
count += szExt::WRITEALL(out, (sz::Byte)Minor );
|
||||
|
||||
sz::UInt32 StartHeaderCRC, NextHeaderCRC;
|
||||
|
||||
SFileInfo const& fi = m_lFileInfo.back();
|
||||
sz::UInt64 NextHeaderOffset = fi.offset + fi.size;
|
||||
sz::UInt64 NextHeaderSize = m_ssInfoStream.str().length()*sizeof(char);
|
||||
NextHeaderCRC = sz::CrcCalc(m_ssInfoStream.str().c_str(),(::size_t)NextHeaderSize);
|
||||
|
||||
std::stringstream sstemp;
|
||||
count += szExt::WRITEALL(sstemp, (sz::UInt64)NextHeaderOffset );
|
||||
count += szExt::WRITEALL(sstemp, (sz::UInt64)NextHeaderSize );
|
||||
count += szExt::WRITEALL(sstemp, (sz::UInt32)NextHeaderCRC );
|
||||
StartHeaderCRC = sz::CrcCalc(sstemp.str().c_str(), sstemp.str().length()*sizeof(char));
|
||||
|
||||
count += szExt::WRITEALL(out, (sz::UInt32)StartHeaderCRC );
|
||||
out << sstemp.str();
|
||||
|
||||
return true;
|
||||
}
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeNextHeader(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdHeader);
|
||||
|
||||
// this->WriteArchiveProperties(out);
|
||||
|
||||
// this->WriteAdditionalStreamsInfo(out)
|
||||
|
||||
//
|
||||
this->writeMainStreamsInfo(out);
|
||||
|
||||
//
|
||||
this->writeFilesInfo(out);
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeMainStreamsInfo(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdMainStreamsInfo );
|
||||
|
||||
this->writePackInfo(out);
|
||||
|
||||
this->writeUnPackInfo(out);
|
||||
|
||||
this->writeSubStreamsInfo(out);
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool vfs::CCreateUncompressed7zLibrary::writePackInfo(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdPackInfo );
|
||||
szExt::WRITE(out, (sz::UInt64)0 ); // data offset
|
||||
szExt::WRITE(out, (sz::UInt32)m_lFileInfo.size() );
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdSize );
|
||||
std::list<SFileInfo>::iterator it = m_lFileInfo.begin();
|
||||
for(;it != m_lFileInfo.end(); ++it)
|
||||
{
|
||||
szExt::WRITE(out, (sz::UInt64)it->size );
|
||||
}
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
|
||||
return true;
|
||||
}
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeUnPackInfo(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdUnpackInfo );
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdFolder );
|
||||
szExt::WRITE(out, (sz::UInt64)m_lFileInfo.size() );
|
||||
szExt::WRITE(out, (sz::Byte)0 ); // External
|
||||
|
||||
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
|
||||
for(;fit != m_lFileInfo.end(); ++fit)
|
||||
{
|
||||
this->writeFolder(out);
|
||||
}
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdCodersUnpackSize );
|
||||
fit = m_lFileInfo.begin();
|
||||
for(;fit != m_lFileInfo.end(); ++fit)
|
||||
{
|
||||
szExt::WRITE(out, (sz::UInt64)fit->size );
|
||||
}
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
|
||||
|
||||
return true;
|
||||
}
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeSubStreamsInfo(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdSubStreamsInfo );
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdCRC );
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)1 ); // early out - all CRCs defined
|
||||
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
|
||||
for(;fit != m_lFileInfo.end(); ++fit )
|
||||
{
|
||||
szExt::WRITEALL(out, (sz::UInt32)fit->CRC);
|
||||
}
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeFolder(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::UInt32)1 ); // NumCoders
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)1 ); // MainByte
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)0 ); // Methods
|
||||
|
||||
return true;
|
||||
}
|
||||
bool vfs::CCreateUncompressed7zLibrary::writeFilesInfo(std::ostream& out)
|
||||
{
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdFilesInfo );
|
||||
|
||||
vfs::UInt64 num_files = (m_lFileInfo.size()+m_mapDirInfo.size());
|
||||
szExt::WRITE(out, (sz::UInt64)num_files );
|
||||
|
||||
// empty stream -> pack info in bit-vector
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEmptyStream );
|
||||
sz::UInt64 num_empty64 = num_files/8 + (num_files%8 == 0 ? 0 : 1);
|
||||
::size_t num_empty = (::size_t)num_empty64;
|
||||
VFS_THROW_IFF(num_empty == num_empty64, L"WTF");
|
||||
|
||||
sz::Byte *empty_vector = new sz::Byte[num_empty];
|
||||
memset(empty_vector,0,(::size_t)num_empty);
|
||||
for(::size_t e=m_lFileInfo.size(); e < num_files; ++e)
|
||||
{
|
||||
::size_t index = e / 8;
|
||||
empty_vector[index] |= 1 << (7 - e%8);
|
||||
}
|
||||
szExt::WRITE(out, (sz::UInt64)num_empty ); // size
|
||||
szExt::WRITEBUFFER(out, empty_vector, (::size_t)num_empty);
|
||||
delete[] empty_vector;
|
||||
|
||||
// names
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdName );
|
||||
::size_t count = 0;
|
||||
std::stringstream name_stream;
|
||||
count += szExt::WRITE(name_stream, (sz::Byte)0 ); // switch
|
||||
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
|
||||
for(;fit != m_lFileInfo.end(); ++fit)
|
||||
{
|
||||
count += (::size_t)this->writeFileName(name_stream, fit->name);
|
||||
}
|
||||
std::map<vfs::String::str_t,SFileInfo>::iterator dit = m_mapDirInfo.begin();
|
||||
for(;dit != m_mapDirInfo.end(); ++dit)
|
||||
{
|
||||
count += (::size_t)this->writeFileName(name_stream, dit->second.name);
|
||||
}
|
||||
szExt::WRITE(out, (sz::UInt64)count ); // size
|
||||
szExt::WRITEBUFFER(out, name_stream.str().c_str(), name_stream.str().length() );
|
||||
|
||||
//szExt::WRITE(out, (sz::Byte)sz::k7zIdEmptyFile );
|
||||
//szExt::WRITE(out, (sz::Byte)sz::k7zIdCTime ); // create
|
||||
//szExt::WRITE(out, (sz::Byte)sz::k7zIdATime ); // last access
|
||||
//szExt::WRITE(out, (sz::Byte)sz::k7zIdMTime ); // write
|
||||
|
||||
//szExt::WRITE(out, (sz::Byte)sz::k7zIdWinAttributes );
|
||||
|
||||
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs::size_t vfs::CCreateUncompressed7zLibrary::writeFileName(std::ostream& out, vfs::String const& filename)
|
||||
{
|
||||
::size_t count = 0;
|
||||
VFS_THROW_IFF(filename.length(), L"zero length name");
|
||||
count += szExt::WRITEBUFFER(out, filename.c_str(), filename.length());
|
||||
count += szExt::WRITE(out, (sz::Byte)0);
|
||||
count += szExt::WRITE(out, (sz::Byte)0);
|
||||
return (vfs::size_t)count;
|
||||
}
|
||||
|
||||
#endif // VFS_WITH_7ZIP
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
## Ext
|
||||
|
||||
if(BFVFS_WITH_7ZIP)
|
||||
set(INCLUDE_Ext_7zip
|
||||
${MOD_INCLUDE}/7z/vfs_7z_library.h
|
||||
${MOD_INCLUDE}/7z/vfs_create_7z_library.h
|
||||
)
|
||||
set(SOURCE_Ext_7zip
|
||||
${MOD_SOURCE}/7z/vfs_7z_library.cpp
|
||||
${MOD_SOURCE}/7z/vfs_create_7z_library.cpp
|
||||
)
|
||||
source_group("Ext" FILES ${INCLUDE_Ext_7zip} ${SOURCE_Ext_7zip})
|
||||
endif()
|
||||
|
||||
if(BFVFS_WITH_SLF)
|
||||
set(INCLUDE_Ext_slf
|
||||
${MOD_INCLUDE}/slf/vfs_slf_library.h
|
||||
)
|
||||
set(SOURCE_Ext_slf
|
||||
${MOD_SOURCE}/slf/vfs_slf_library.cpp
|
||||
)
|
||||
source_group("Ext" FILES ${INCLUDE_Ext_slf} ${SOURCE_Ext_slf})
|
||||
endif()
|
||||
|
||||
set(${mod}_files
|
||||
${INCLUDE_Ext_7zip} ${SOURCE_Ext_7zip}
|
||||
${INCLUDE_Ext_slf} ${SOURCE_Ext_slf}
|
||||
CACHE INTERNAL ""
|
||||
)
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* bfVFS : vfs/Ext/slf/vfs_slf_library.cpp
|
||||
* - implements Library interface, creates library object from SLF archive files
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef VFS_WITH_SLF
|
||||
|
||||
#include <vfs/Ext/slf/vfs_slf_library.h>
|
||||
#include <vfs/Core/Location/vfs_lib_dir.h>
|
||||
#include <vfs/vfs_config.h>
|
||||
#include <vfs/Core/Interface/vfs_directory_interface.h>
|
||||
#include <vfs/Core/File/vfs_lib_file.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace slf
|
||||
{
|
||||
typedef vfs::UInt32 DWORD;
|
||||
// copy from WinDef.h
|
||||
typedef struct _FILETIME {
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME, *PFILETIME, *LPFILETIME;
|
||||
|
||||
typedef void* HANDLE;
|
||||
|
||||
const vfs::UInt32 FILENAME_SIZE = 256;
|
||||
const vfs::UInt32 PATH_SIZE = 80;
|
||||
|
||||
const vfs::UInt32 FILE_OK = 0;
|
||||
const vfs::UInt32 FILE_DELETED = 0xff;
|
||||
const vfs::UInt32 FILE_OLD = 1;
|
||||
const vfs::UInt32 FILE_DOESNT_EXIST = 0xfe;
|
||||
|
||||
struct LIBHEADER
|
||||
{
|
||||
vfs::Byte sLibName[ FILENAME_SIZE ];
|
||||
vfs::Byte sPathToLibrary[ FILENAME_SIZE ];
|
||||
vfs::Int32 iEntries;
|
||||
vfs::Int32 iUsed;
|
||||
vfs::UInt16 iSort;
|
||||
vfs::UInt16 iVersion;
|
||||
vfs::UByte fContainsSubDirectories;
|
||||
vfs::Int32 iReserved;
|
||||
};
|
||||
|
||||
struct DIRENTRY
|
||||
{
|
||||
vfs::Byte sFileName[ FILENAME_SIZE ];
|
||||
vfs::UInt32 uiOffset;
|
||||
vfs::UInt32 uiLength;
|
||||
vfs::UInt8 ubState;
|
||||
vfs::UInt8 ubReserved;
|
||||
FILETIME sFileTime;
|
||||
vfs::UInt16 usReserved2;
|
||||
};
|
||||
}; // end namespace slf
|
||||
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
vfs::CSLFLibrary::CSLFLibrary(tReadableFile *pLibraryFile, vfs::Path const& sMountPoint, bool bOwnFile)
|
||||
: vfs::CUncompressedLibraryBase(pLibraryFile,sMountPoint,bOwnFile)
|
||||
{};
|
||||
|
||||
vfs::CSLFLibrary::~CSLFLibrary()
|
||||
{
|
||||
}
|
||||
|
||||
bool vfs::CSLFLibrary::init()
|
||||
{
|
||||
if(!m_libraryFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
vfs::COpenReadFile rfile(m_libraryFile);
|
||||
|
||||
slf::LIBHEADER LibFileHeader;
|
||||
vfs::size_t bytesRead = m_libraryFile->read((vfs::Byte*)&LibFileHeader, sizeof( slf::LIBHEADER ));
|
||||
VFS_THROW_IFF(bytesRead == sizeof( slf::LIBHEADER ), L"");
|
||||
|
||||
vfs::Path oLibPath;
|
||||
//if the library has a path
|
||||
if( strlen( (char*)LibFileHeader.sPathToLibrary ) != 0 )
|
||||
{
|
||||
oLibPath = vfs::Path( LibFileHeader.sPathToLibrary );
|
||||
}
|
||||
else
|
||||
{
|
||||
//else the library name does not contain a path ( most likely either an error or it is the default path )
|
||||
oLibPath = vfs::Path( vfs::Const::EMPTY() );
|
||||
}
|
||||
if(m_mountPoint.empty())
|
||||
{
|
||||
m_mountPoint = oLibPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mountPoint += oLibPath;
|
||||
}
|
||||
|
||||
//place the file pointer at the begining of the file headers ( they are at the end of the file )
|
||||
m_libraryFile->setReadPosition(-( LibFileHeader.iEntries * (vfs::Int32)sizeof(slf::DIRENTRY) ), vfs::IBaseFile::SD_END);
|
||||
|
||||
//loop through the library and determine the number of files that are FILE_OK
|
||||
//ie. so we dont load the old or deleted files
|
||||
slf::DIRENTRY DirEntry;
|
||||
vfs::Path oDir, oFile;
|
||||
vfs::Path oDirPath;
|
||||
for(vfs::UInt32 uiLoop=0; uiLoop < (vfs::UInt32)LibFileHeader.iEntries; uiLoop++ )
|
||||
{
|
||||
//read in the file header
|
||||
//memset(&DirEntry,0,sizeof(DirEntry));
|
||||
bytesRead = m_libraryFile->read((Byte*)&DirEntry, sizeof( slf::DIRENTRY ));
|
||||
VFS_THROW_IFF(bytesRead == sizeof( slf::DIRENTRY ), L"");
|
||||
|
||||
if( DirEntry.ubState == slf::FILE_OK )
|
||||
{
|
||||
vfs::Path sPath(vfs::String::as_utf16(DirEntry.sFileName));
|
||||
sPath.splitLast(oDir,oFile);
|
||||
oDirPath = m_mountPoint;
|
||||
if(!oDir.empty())
|
||||
{
|
||||
oDirPath += oDir;
|
||||
}
|
||||
|
||||
// get or create according directory object
|
||||
vfs::TDirectory<ILibrary::tWriteType>* pLD = NULL;
|
||||
tDirCatalogue::iterator it = m_dirs.find(oDirPath);
|
||||
if(it != m_dirs.end())
|
||||
{
|
||||
pLD = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
pLD = new vfs::CLibDirectory(oDirPath,oDirPath);
|
||||
m_dirs.insert(std::make_pair(oDirPath,pLD));
|
||||
}
|
||||
// create file
|
||||
vfs::CLibFile *pFile = vfs::CLibFile::create(oFile,pLD,this);
|
||||
// add file to directory
|
||||
VFS_THROW_IFF(pLD->addFile(pFile), L"");
|
||||
|
||||
// link file data struct to file object
|
||||
m_fileData.insert(std::make_pair(pFile, SFileData(DirEntry.uiLength, DirEntry.uiOffset)));
|
||||
} // end if
|
||||
} // end for
|
||||
return true;
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_LOG_ERROR(ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VFS_WITH_SLF
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
## Tools
|
||||
|
||||
set(INCLUDE_Tools
|
||||
${MOD_INCLUDE}/vfs_allocator.h
|
||||
${MOD_INCLUDE}/vfs_file_logger.h
|
||||
${MOD_INCLUDE}/vfs_hp_timer.h
|
||||
${MOD_INCLUDE}/vfs_log.h
|
||||
${MOD_INCLUDE}/vfs_parser_tools.h
|
||||
${MOD_INCLUDE}/vfs_profiler.h
|
||||
${MOD_INCLUDE}/vfs_property_container.h
|
||||
${MOD_INCLUDE}/vfs_tools.h
|
||||
)
|
||||
set(SOURCE_Tools
|
||||
${MOD_SOURCE}/vfs_allocator.cpp
|
||||
${MOD_SOURCE}/vfs_file_logger.cpp
|
||||
${MOD_SOURCE}/vfs_hp_timer.cpp
|
||||
${MOD_SOURCE}/vfs_log.cpp
|
||||
${MOD_SOURCE}/vfs_parser_tools.cpp
|
||||
${MOD_SOURCE}/vfs_profiler.cpp
|
||||
${MOD_SOURCE}/vfs_property_container.cpp
|
||||
${MOD_SOURCE}/vfs_tools.cpp
|
||||
)
|
||||
source_group(Tools FILES ${INCLUDE_Tools} ${SOURCE_Tools})
|
||||
|
||||
set(${mod}_files
|
||||
${INCLUDE_Tools} ${SOURCE_Tools}
|
||||
CACHE INTERNAL ""
|
||||
)
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_allocator.cpp
|
||||
* - allocator class to reserve memory blockwise for a larger amount of objects (that have constant size)
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Tools/vfs_allocator.h>
|
||||
|
||||
std::vector<vfs::IAllocator*> vfs::ObjectAllocator::_valloc;
|
||||
|
||||
void vfs::ObjectAllocator::registerAllocator(vfs::IAllocator* allocator)
|
||||
{
|
||||
_valloc.push_back(allocator);
|
||||
}
|
||||
void vfs::ObjectAllocator::clear()
|
||||
{
|
||||
std::vector<IAllocator*>::iterator it = _valloc.begin();
|
||||
for(; it != _valloc.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
*it = NULL;
|
||||
}
|
||||
_valloc.clear();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_file_logger.cpp
|
||||
* - implements Logging iterface in the Aspects module by using the vfs::Log class
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Tools/vfs_file_logger.h>
|
||||
|
||||
vfs::FileLogger::FileLogger(vfs::Path const& log_file, bool append, vfs::Log::EFlushMode flush_mode)
|
||||
: m_log( *vfs::Log::create(log_file, append, flush_mode) )
|
||||
{
|
||||
m_log.Reserve();
|
||||
m_clock.startTimer();
|
||||
}
|
||||
|
||||
vfs::FileLogger::FileLogger(vfs::tWritableFile* file, bool append, vfs::Log::EFlushMode flush_mode)
|
||||
: m_log( *vfs::Log::create(file,append, flush_mode) )
|
||||
{
|
||||
m_log.Reserve();
|
||||
m_clock.startTimer();
|
||||
}
|
||||
|
||||
|
||||
vfs::FileLogger::~FileLogger()
|
||||
{
|
||||
m_log.destroy();
|
||||
}
|
||||
|
||||
void vfs::FileLogger::Msg(const wchar_t* msg)
|
||||
{
|
||||
m_log << "[" << m_clock.running() << "] : " << vfs::String::as_utf8(msg) << vfs::Log::endl;
|
||||
}
|
||||
|
||||
void vfs::FileLogger::Msg(const char* msg)
|
||||
{
|
||||
m_log << "[" << m_clock.running() << "] : " << msg << vfs::Log::endl;
|
||||
}
|
||||
|
||||
void vfs::FileLogger::Msg(vfs::String const& msg)
|
||||
{
|
||||
this->Msg(msg.c_str());
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_hp_timer.cpp
|
||||
* - high performance/precision timer, used by profiler
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Tools/vfs_hp_timer.h>
|
||||
|
||||
vfs::HPTimer::HPTimer() : is_running(false)
|
||||
{
|
||||
#ifdef WIN32
|
||||
QueryPerformanceFrequency(&ticksPerSecond);
|
||||
#endif
|
||||
}
|
||||
|
||||
vfs::HPTimer::~HPTimer()
|
||||
{
|
||||
}
|
||||
|
||||
void vfs::HPTimer::startTimer()
|
||||
{
|
||||
#ifdef WIN32
|
||||
QueryPerformanceCounter(&tick);
|
||||
#elif __linux__
|
||||
gettimeofday(&t1,0);
|
||||
#endif
|
||||
is_running = true;
|
||||
}
|
||||
|
||||
long long vfs::HPTimer::ticks()
|
||||
{
|
||||
if(is_running)
|
||||
{
|
||||
#ifdef WIN32
|
||||
QueryPerformanceCounter(&tick2);
|
||||
return tick2.QuadPart - tick.QuadPart;
|
||||
#elif __linux__
|
||||
gettimeofday(&t2,0);
|
||||
return t2.tv_usec - t1.tv_usec;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
double vfs::HPTimer::running()
|
||||
{
|
||||
if(is_running)
|
||||
{
|
||||
#ifdef WIN32
|
||||
QueryPerformanceCounter(&tick2);
|
||||
return (double)(tick2.QuadPart - tick.QuadPart)/(double)ticksPerSecond.QuadPart;
|
||||
#elif __linux__
|
||||
gettimeofday(&t2,0);
|
||||
return (double)(t2.tv_usec - t1.tv_usec)/1000000.0;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vfs::HPTimer::stopTimer()
|
||||
{
|
||||
#ifdef WIN32
|
||||
QueryPerformanceCounter(&tick2);
|
||||
#elif __linux__
|
||||
gettimeofday(&t2,0);
|
||||
#endif
|
||||
is_running = false;
|
||||
}
|
||||
|
||||
double vfs::HPTimer::getElapsedTimeInSeconds()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return (double)(tick2.QuadPart - tick.QuadPart)/(double)ticksPerSecond.QuadPart;
|
||||
#elif __linux__
|
||||
return (double)(t2.tv_usec - t1.tv_usec)/1000000.0;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_log.cpp
|
||||
* - simple file logger
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Tools/vfs_log.h>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef WIN32
|
||||
static const char ENDL[] = "\r\n";
|
||||
#else
|
||||
static const char ENDL[] = "\n";
|
||||
#endif
|
||||
|
||||
typedef std::list<vfs::Log*> LogList_t;
|
||||
static LogList_t* __logs;
|
||||
std::list<vfs::Log*>& vfs::Log::_logs()
|
||||
{
|
||||
if(!__logs)
|
||||
{
|
||||
__logs = new LogList_t;
|
||||
}
|
||||
return *__logs;
|
||||
}
|
||||
|
||||
vfs::Log* vfs::Log::create(vfs::Path const& fileName, bool append, EFlushMode flushMode)
|
||||
{
|
||||
_logs().push_back(new vfs::Log(fileName, true, append, flushMode));
|
||||
return _logs().back();
|
||||
}
|
||||
vfs::Log* vfs::Log::create(vfs::tWritableFile* file, bool append, EFlushMode flushMode)
|
||||
{
|
||||
_logs().push_back(new vfs::Log(file, append, flushMode));
|
||||
return _logs().back();
|
||||
}
|
||||
|
||||
void vfs::Log::flushDeleteAll()
|
||||
{
|
||||
LogList_t::iterator it = _logs().begin();
|
||||
for(; it != _logs().end(); ++it)
|
||||
{
|
||||
(*it)->flush();
|
||||
(*it)->Release();
|
||||
}
|
||||
_logs().clear();
|
||||
}
|
||||
|
||||
void vfs::Log::flushReleaseAll()
|
||||
{
|
||||
LogList_t::iterator it = _logs().begin();
|
||||
for(; it != _logs().end(); ++it)
|
||||
{
|
||||
(*it)->releaseFile();
|
||||
}
|
||||
}
|
||||
|
||||
vfs::String vfs::Log::_shared_id_str;
|
||||
|
||||
vfs::String const& vfs::Log::getSharedString()
|
||||
{
|
||||
return _shared_id_str;
|
||||
}
|
||||
|
||||
void vfs::Log::setSharedString(vfs::String const& str)
|
||||
{
|
||||
_shared_id_str = str;
|
||||
}
|
||||
|
||||
|
||||
vfs::Log::Log(vfs::Path const& fileName, bool use_vfs_file, bool append, EFlushMode flushMode)
|
||||
: IRefCountable(),
|
||||
_filename(fileName), _file(NULL), _own_file(false),
|
||||
_first_write(true), _flush_mode(flushMode), _append(append),
|
||||
_buffer_size(0), _buffer_test_size(512)
|
||||
{};
|
||||
|
||||
vfs::Log::Log(vfs::tWritableFile* file, bool append, EFlushMode flushMode)
|
||||
: IRefCountable(),
|
||||
_file(file), _own_file(false),
|
||||
_first_write(true), _flush_mode(flushMode), _append(append),
|
||||
_buffer_size(0), _buffer_test_size(512)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
vfs::Log::~Log()
|
||||
{
|
||||
// the final flush
|
||||
flush();
|
||||
|
||||
// also delete file pointer if we created it
|
||||
if(_file && _own_file)
|
||||
{
|
||||
delete _file;
|
||||
_file = NULL;
|
||||
}
|
||||
|
||||
// one extra unlock wouldn't hurt
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
int vfs::Log::Reserve()
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return this->Register();
|
||||
}
|
||||
int vfs::Log::Release()
|
||||
{
|
||||
_mutex.lock();
|
||||
int tmp_count = this->UnRegister();
|
||||
if(tmp_count > 0)
|
||||
{
|
||||
_mutex.unlock();
|
||||
}
|
||||
// otherwise the mutex object is destroyed at that time
|
||||
return tmp_count;
|
||||
}
|
||||
int vfs::Log::RefCount()
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return this->GetRefCount();
|
||||
}
|
||||
|
||||
|
||||
void vfs::Log::destroy()
|
||||
{
|
||||
// no need to lock here as 'flush' and 'Release' do it themselves
|
||||
this->flush();
|
||||
if(this->Release() <= 0)
|
||||
{
|
||||
// object is deleted, so remove it now from the static list
|
||||
_logs().remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::Log::releaseFile()
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
this->flush();
|
||||
this->_file = NULL;
|
||||
}
|
||||
|
||||
vfs::Log& vfs::Log::operator<<(vfs::UInt64 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::UInt32 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::UInt16 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::UInt8 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
|
||||
vfs::Log& vfs::Log::operator<<(vfs::Int64 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::Int32 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::Int16 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::Int8 const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
vfs::Log& vfs::Log::operator<<(DWORD const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
#endif
|
||||
vfs::Log& vfs::Log::operator<<(float const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(double const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
return pushNumber(t);
|
||||
}
|
||||
|
||||
vfs::Log& vfs::Log::operator<<(const char* t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
_buffer << t;
|
||||
_buffer_size += strlen(t);
|
||||
_test_flush();
|
||||
return *this;
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(const wchar_t* t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
std::string s = vfs::String::as_utf8(t);
|
||||
_buffer << s;
|
||||
_buffer_size += s.length();
|
||||
_test_flush();
|
||||
return *this;
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(std::string const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
_buffer << t;
|
||||
_buffer_size += t.length();
|
||||
_test_flush();
|
||||
return *this;
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(std::wstring const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
std::string s = vfs::String::as_utf8(t);
|
||||
_buffer << s;
|
||||
_buffer_size += s.length();
|
||||
_test_flush();
|
||||
return *this;
|
||||
}
|
||||
vfs::Log& vfs::Log::operator<<(vfs::String const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
std::string s = t.utf8();
|
||||
_buffer << s;
|
||||
_buffer_size += s.length();
|
||||
_test_flush();
|
||||
return *this;
|
||||
}
|
||||
|
||||
vfs::Log& vfs::Log::operator<<(void* const& t)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
_buffer << t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
vfs::Log& vfs::Log::operator<<(vfs::Log::_endl const& endl)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
_buffer << ENDL;
|
||||
_buffer_size += sizeof(ENDL)-1;
|
||||
if(_flush_mode == vfs::Log::FLUSH_ON_ENDL) flush();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
vfs::Log& vfs::Log::endl()
|
||||
{
|
||||
_buffer << ENDL;
|
||||
_buffer_size += sizeof(ENDL)-1;
|
||||
_test_flush();
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
void vfs::Log::setAppend(bool append)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
_append = append;
|
||||
}
|
||||
|
||||
void vfs::Log::setBufferSize(vfs::UInt32 bufferSize)
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
_buffer_test_size = bufferSize;
|
||||
}
|
||||
|
||||
void vfs::Log::_test_flush(bool force)
|
||||
{
|
||||
if( (_flush_mode == FLUSH_IMMEDIATELY) ||
|
||||
(_flush_mode == FLUSH_BUFFER && _buffer_size > _buffer_test_size) ||
|
||||
(/*_flush_mode == FLUSH_ON_DELETE &&*/ force == true) )
|
||||
{
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vfs::Log::EFlushMode vfs::Log::flushMode()
|
||||
{
|
||||
return _flush_mode;
|
||||
}
|
||||
void vfs::Log::flushMode(vfs::Log::EFlushMode fmode)
|
||||
{
|
||||
_flush_mode = fmode;
|
||||
}
|
||||
|
||||
#include <ctime>
|
||||
#include <vfs/Core/vfs.h>
|
||||
|
||||
void vfs::Log::flush()
|
||||
{
|
||||
VFS_LOCK(_mutex);
|
||||
::size_t buflen = _buffer.str().length();
|
||||
if(buflen == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!_file)
|
||||
{
|
||||
VFS_THROW_IFF(!_filename.empty(), L"_file is NULL and _filename is empty");
|
||||
//vfs::CVirtualProfile *prof = getVFS()->getProfileStack()->topProfile();
|
||||
//if( prof && prof->cWritable )
|
||||
if(vfs::canWrite())
|
||||
{
|
||||
try
|
||||
{
|
||||
vfs::COpenWriteFile file_raii(_filename,true,!_append);
|
||||
_file = &file_raii.file();
|
||||
file_raii.release();
|
||||
_own_file = false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
_file = vfs::tWritableFile::cast(new vfs::CFile(_filename));
|
||||
_file->openWrite(true,!_append);
|
||||
_own_file = true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vfs::COpenWriteFile wfile(_file);
|
||||
if(_append)
|
||||
{
|
||||
wfile->setWritePosition(0,vfs::IBaseFile::SD_END);
|
||||
}
|
||||
|
||||
if(_first_write)
|
||||
{
|
||||
time_t rawtime;
|
||||
time ( &rawtime );
|
||||
std::string datetime(ctime(&rawtime));
|
||||
std::string s_out;
|
||||
|
||||
vfs::size_t wloc = wfile->getWritePosition();
|
||||
if(wloc > 0)
|
||||
{
|
||||
s_out = ENDL;
|
||||
}
|
||||
s_out += " *** ";
|
||||
s_out += datetime.substr(0,datetime.length()-1);
|
||||
s_out += " *** ";
|
||||
s_out += ENDL;
|
||||
s_out += "[ ";
|
||||
s_out += _shared_id_str.utf8();
|
||||
s_out += " ]";
|
||||
s_out += ENDL;
|
||||
s_out += ENDL;
|
||||
|
||||
wfile->write(s_out.c_str(), s_out.length());
|
||||
_first_write = false;
|
||||
}
|
||||
|
||||
wfile->write(_buffer.str().c_str(), buflen);
|
||||
_buffer.str("");
|
||||
_buffer.clear();
|
||||
_buffer_size = 0;
|
||||
|
||||
_append = true;
|
||||
}
|
||||
|
||||
void vfs::Log::lock()
|
||||
{
|
||||
_mutex.lock();
|
||||
}
|
||||
void vfs::Log::unlock()
|
||||
{
|
||||
_mutex.unlock();
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_parser_tools.cpp
|
||||
* - read file line-wise,
|
||||
* - split string into tokens,
|
||||
* - simple pattern matching
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Core/vfs.h>
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
#include <vfs/Tools/vfs_parser_tools.h>
|
||||
#include <vfs/Tools/vfs_tools.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
vfs::CReadLine::CReadLine(vfs::tReadableFile& rFile)
|
||||
: _file(rFile), _buffer_pos(0), _eof(false)
|
||||
{
|
||||
memset(_buffer,0,sizeof(_buffer));
|
||||
|
||||
vfs::COpenReadFile rfile(&_file);
|
||||
_bytes_left = rfile->getSize();
|
||||
fillBuffer();
|
||||
vfs::UByte utf8bom[3] = {0xef,0xbb,0xbf};
|
||||
if(memcmp(utf8bom, &_buffer[0],3) == 0)
|
||||
{
|
||||
_buffer_pos += 3;
|
||||
}
|
||||
rfile.release();
|
||||
};
|
||||
|
||||
vfs::CReadLine::~CReadLine()
|
||||
{
|
||||
if(_file.isOpenRead())
|
||||
{
|
||||
_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::CReadLine::fillBuffer()
|
||||
{
|
||||
if(_eof)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vfs::size_t bytesRead = BUFFER_SIZE < _bytes_left ? BUFFER_SIZE : _bytes_left;
|
||||
try
|
||||
{
|
||||
vfs::COpenReadFile rfile(&_file);
|
||||
|
||||
// fill the buffer from the start, BUFFER_SIZE charactes at max (_buffer has BUFFER_SIZE+1 elements)
|
||||
VFS_THROW_IFF(bytesRead == _file.read(&_buffer[0], bytesRead), L"");
|
||||
rfile.release();
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(L"", ex);
|
||||
}
|
||||
|
||||
_bytes_left -= bytesRead;
|
||||
_eof = (_bytes_left == 0);
|
||||
|
||||
|
||||
// bite-wise read files usually terminate a line with \n (or \r\n on WIN32)
|
||||
// line-wise read files just returns 0-terminated string
|
||||
|
||||
// always terminate the string with 0
|
||||
_buffer[bytesRead] = 0;
|
||||
|
||||
_buffer_pos = 0;
|
||||
_buffer_last = bytesRead;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vfs::CReadLine::fromBuffer(std::string& line)
|
||||
{
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
if(_buffer_pos < _buffer_last)
|
||||
{
|
||||
// start where we left last time
|
||||
vfs::Byte *temp = &_buffer[_buffer_pos];
|
||||
vfs::size_t start_pos = _buffer_pos;
|
||||
// go until we hit 0. since our buffer is always 0 terminated, the second test should be redundant.
|
||||
while(*temp && (_buffer_pos < _buffer_last))
|
||||
{
|
||||
// stop when we find a line terminator
|
||||
if(*temp == '\n' || *temp == '\r' /* || *temp == '\0' */)
|
||||
{
|
||||
break;
|
||||
}
|
||||
temp++;
|
||||
_buffer_pos++;
|
||||
}
|
||||
// need to append substring, as we might have refilles the buffer (because there was no \n or \r\n terminator)
|
||||
line.append( (char*)&_buffer[start_pos], _buffer_pos - start_pos );
|
||||
|
||||
// if we reach the (real) end of the buffer (that always terminate with 0), this means
|
||||
// that there was no line terminator and that we have to refill the buffer.
|
||||
if( _buffer_pos < BUFFER_SIZE && (*temp == '\n' || *temp == '\r' || *temp == 0) )
|
||||
{
|
||||
// found the line terminator
|
||||
if(*temp == '\r')
|
||||
{
|
||||
// the \r is most probably followed by \n. 'swallow' both characters
|
||||
*temp++;
|
||||
_buffer_pos++;
|
||||
if( (_buffer_pos < BUFFER_SIZE) && (*temp == '\n' || *temp == 0) )
|
||||
{
|
||||
// increase buffer position, so that we can start with a valid character in the next run
|
||||
_buffer_pos++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
done = !fillBuffer();
|
||||
}
|
||||
}
|
||||
else if(*temp == '\n' || *temp == 0)
|
||||
{
|
||||
// increase buffer position, so that we can start with a valid character in the next run
|
||||
_buffer_pos++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
done = !fillBuffer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
done = !fillBuffer();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::CReadLine::getLine(std::string& line)
|
||||
{
|
||||
line.clear();
|
||||
return fromBuffer(line);
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
vfs::CTokenizer::CTokenizer(vfs::String const& str)
|
||||
: m_list(str), m_current(0), m_next(0)
|
||||
{};
|
||||
|
||||
vfs::CTokenizer::~CTokenizer()
|
||||
{};
|
||||
|
||||
bool vfs::CTokenizer::next(vfs::String& token, vfs::String::char_t delimeter)
|
||||
{
|
||||
if(m_next != vfs::String::str_t::npos)
|
||||
{
|
||||
m_next = m_list.c_wcs().find_first_of(delimeter, m_current);
|
||||
if(m_next != vfs::String::str_t::npos)
|
||||
{
|
||||
token.r_wcs().assign(vfs::trimString(m_list,m_current,m_next > m_current ? m_next-1 : m_current).c_wcs());
|
||||
m_current = m_next+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// last or only entry
|
||||
token.r_wcs().assign(vfs::trimString(m_list,m_current,m_list.length()).c_wcs());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
/**
|
||||
* try to recursively match the pattern
|
||||
*/
|
||||
bool vfs::matchPattern(vfs::String const& sPattern, vfs::String const& sStr)
|
||||
{
|
||||
return matchPattern(sPattern,sStr.c_wcs());
|
||||
}
|
||||
|
||||
bool vfs::matchPattern(vfs::String const& sPattern, vfs::String::str_t const& sStr)
|
||||
{
|
||||
vfs::String::str_t const& pat = sPattern.c_wcs();
|
||||
|
||||
vfs::String::size_t star = pat.find_first_of(vfs::Const::STAR());
|
||||
if(star == vfs::String::str_t::npos)
|
||||
{
|
||||
return vfs::StrCmp::Equal( pat, sStr );
|
||||
}
|
||||
else if(star == 0)
|
||||
{
|
||||
if(pat.length() == 1)
|
||||
{
|
||||
// there is only the '*' -> matches all strings
|
||||
return true;
|
||||
}
|
||||
vfs::String::char_t atpos1 = pat.at(1);
|
||||
vfs::String::size_t match = vfs::String::size_t(-1);
|
||||
do
|
||||
{
|
||||
match = sStr.find_first_of(atpos1,match+1);
|
||||
if(match == vfs::String::str_t::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while(!matchPattern( pat.substr(1,pat.length()-1), sStr.substr(match,sStr.length()-match) ));
|
||||
return true;
|
||||
}
|
||||
else // if(star > 0)
|
||||
{
|
||||
// check if characters before * match
|
||||
if(!vfs::StrCmp::Equal(pat.substr(0,star), sStr.substr(0,star)) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return matchPattern( pat.substr(star,pat.length()-star), sStr.substr(star,sStr.length()-star) );
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_profiler.cpp
|
||||
* - basic profiler class and macros to measure execution time of code blocks
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define NOMINMAX
|
||||
#include <vfs/Tools/vfs_profiler.h>
|
||||
|
||||
#include <vfs/Core/vfs_types.h>
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
class CProfileStarter
|
||||
{
|
||||
public:
|
||||
CProfileStarter()
|
||||
{
|
||||
Profiler::getProfiler();
|
||||
}
|
||||
};
|
||||
static CProfileStarter starter;
|
||||
}
|
||||
|
||||
vfs::Profiler& vfs::Profiler::getProfiler()
|
||||
{
|
||||
static Profiler* _prof = new Profiler;
|
||||
return *_prof;
|
||||
}
|
||||
|
||||
vfs::Profiler::Profiler()
|
||||
{
|
||||
m_vMarker.resize(1024);
|
||||
_nextMarker = 0;
|
||||
}
|
||||
|
||||
void vfs::Profiler::clear()
|
||||
{
|
||||
for(unsigned int i = 0; i < _nextMarker; ++i)
|
||||
{
|
||||
m_vMarker[i].markername = "";
|
||||
m_vMarker[i].time = 0;
|
||||
m_vMarker[i].call_count = 0;
|
||||
m_vMarker[i].success_count = 0;
|
||||
m_vMarker[i].fail_count = 0;
|
||||
}
|
||||
_nextMarker = 0;
|
||||
}
|
||||
|
||||
|
||||
vfs::Profiler::tMarkerID vfs::Profiler::registerMarker(const char *marker)
|
||||
{
|
||||
m_vMarker[_nextMarker].markername = marker;
|
||||
return _nextMarker++;
|
||||
}
|
||||
|
||||
void vfs::Profiler::startMarker(tMarkerID id)
|
||||
{
|
||||
m_vMarker[id].timer.startTimer();
|
||||
}
|
||||
|
||||
void vfs::Profiler::stopMarker(tMarkerID id, bool success)
|
||||
{
|
||||
m_vMarker[id].timer.stopTimer();
|
||||
m_vMarker[id].time += m_vMarker[id].timer.getElapsedTimeInSeconds();
|
||||
m_vMarker[id].call_count++;
|
||||
if(success) m_vMarker[id].success_count++;
|
||||
else m_vMarker[id].fail_count++;
|
||||
}
|
||||
|
||||
inline std::string multChar(std::string::value_type c, unsigned int multiplicity)
|
||||
{
|
||||
std::string s;
|
||||
s.resize(multiplicity);
|
||||
for(unsigned int i=0; i<multiplicity; ++i)
|
||||
{
|
||||
s[i] = c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
inline long double perCent(unsigned long value, unsigned long ref)
|
||||
{
|
||||
return 100.0 * ((double)(value)/double(ref));
|
||||
}
|
||||
|
||||
inline long double oneDigit(long double number)
|
||||
{
|
||||
unsigned long temp = (unsigned long)(number * 10);
|
||||
return (temp / 10.0);
|
||||
}
|
||||
|
||||
bool vfs::Profiler::printProfilerState(vfs::Path const& file)
|
||||
{
|
||||
vfs::CFile oFile(file);
|
||||
if(!oFile.openWrite(true,true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// get largest value
|
||||
long double max_time = 0;
|
||||
std::string::size_type max_prefix = 0;
|
||||
for(unsigned int i=0; i<m_vMarker.size(); ++i)
|
||||
{
|
||||
if(m_vMarker[i].time > max_time)
|
||||
{
|
||||
max_time = m_vMarker[i].time;
|
||||
}
|
||||
std::string::size_type prefix_length = m_vMarker[i].markername.length();
|
||||
if(prefix_length > max_prefix)
|
||||
{
|
||||
max_prefix = prefix_length;
|
||||
}
|
||||
}
|
||||
const unsigned int WIDTH = 40;
|
||||
std::stringstream line;
|
||||
long double ld_success, ld_failure;
|
||||
for(unsigned int i=0; i<m_vMarker.size(); ++i)
|
||||
{
|
||||
if(m_vMarker[i].markername.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(m_vMarker[i].markername.length() < WIDTH)
|
||||
{
|
||||
unsigned int space = WIDTH - m_vMarker[i].markername.length();
|
||||
line << m_vMarker[i].markername << multChar(' ',space) << " | ";
|
||||
}
|
||||
else
|
||||
{
|
||||
line << m_vMarker[i].markername.substr(0,WIDTH) << " | ";
|
||||
}
|
||||
if(max_time != 0)
|
||||
{
|
||||
unsigned int num_stars = (unsigned int)(WIDTH * (m_vMarker[i].time / max_time));
|
||||
ld_success = perCent(m_vMarker[i].success_count,m_vMarker[i].call_count);
|
||||
ld_failure = perCent(m_vMarker[i].fail_count,m_vMarker[i].call_count);
|
||||
line << "[" << oneDigit(ld_success) << "|" << oneDigit(ld_failure) << "] "
|
||||
<< multChar('*', num_stars) << multChar(' ', WIDTH - num_stars) << " | ";
|
||||
}
|
||||
line << "C: " << m_vMarker[i].call_count << ", T: " << m_vMarker[i].time << std::endl;
|
||||
//line << std::endl;
|
||||
}
|
||||
std::string useless_copy = line.str();
|
||||
oFile.write(useless_copy.c_str(), (vfs::size_t)(useless_copy.length()*sizeof(std::string::value_type)));
|
||||
oFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void vfs::DumpProfileState(vfs::Path const& path)
|
||||
{
|
||||
vfs::Profiler::getProfiler().printProfilerState(path);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,798 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_property_container.cpp
|
||||
* - <string,string> key-value map with capability to convert values to other types
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/vfs_config.h>
|
||||
|
||||
#include <vfs/Core/vfs.h>
|
||||
#include <vfs/Core/vfs_file_raii.h>
|
||||
#include <vfs/Core/vfs_os_functions.h>
|
||||
#include <vfs/Core/File/vfs_file.h>
|
||||
#include <vfs/Core/File/vfs_buffer_file.h>
|
||||
|
||||
#include <vfs/Tools/vfs_tools.h>
|
||||
#include <vfs/Tools/vfs_parser_tools.h>
|
||||
#include <vfs/Tools/vfs_property_container.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
bool vfs::PropertyContainer::Section::has(vfs::String const& key)
|
||||
{
|
||||
return mapProps.find(key) != mapProps.end();
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::Section::add(vfs::String const& key, vfs::String const& value)
|
||||
{
|
||||
if(!mapProps[key].empty())
|
||||
{
|
||||
mapProps[key] += L", ";
|
||||
}
|
||||
mapProps[key] += value;
|
||||
return true;
|
||||
}
|
||||
|
||||
vfs::String& vfs::PropertyContainer::Section::value(vfs::String const& key)
|
||||
{
|
||||
return mapProps[key];
|
||||
}
|
||||
bool vfs::PropertyContainer::Section::value(vfs::String const& key, vfs::String& value)
|
||||
{
|
||||
tProps::iterator sit = mapProps.find(key);
|
||||
if(sit != mapProps.end())
|
||||
{
|
||||
value.r_wcs().assign(sit->second.c_wcs());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void vfs::PropertyContainer::Section::print(std::ostream& out, vfs::String::str_t sPrefix)
|
||||
{
|
||||
tProps::iterator sit = mapProps.begin();
|
||||
for(; sit != mapProps.end(); ++sit)
|
||||
{
|
||||
out << vfs::String::as_utf8(sPrefix) << sit->first.utf8() << " = " << sit->second.utf8() << "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::Section::clear()
|
||||
{
|
||||
mapProps.clear();
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
void vfs::PropertyContainer::clearContainer()
|
||||
{
|
||||
tSections::iterator it = m_mapProps.begin();
|
||||
for(;it != m_mapProps.end(); ++it)
|
||||
{
|
||||
it->second.clear();
|
||||
}
|
||||
m_mapProps.clear();
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::extractSection(vfs::String::str_t const& readStr, vfs::size_t startPos, vfs::String::str_t& sSection)
|
||||
{
|
||||
// extract section name
|
||||
vfs::size_t close = readStr.find_first_of(L"]", startPos);
|
||||
if( close != vfs::npos && close > startPos)
|
||||
{
|
||||
startPos += 1;
|
||||
sSection = vfs::trimString(readStr,startPos,(vfs::size_t)(close-1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs::PropertyContainer::EOperation vfs::PropertyContainer::extractKeyValue(vfs::String::str_t const &readStr, vfs::size_t startPos, vfs::String::str_t& sKey, vfs::String::str_t& sValue)
|
||||
{
|
||||
vfs::size_t iEqual = readStr.find_first_of(L"+=", startPos);
|
||||
if(iEqual == vfs::npos)
|
||||
{
|
||||
VFS_LOG_WARNING(_BS("WARNING : could not extract key-value pair : ") << readStr << _BS::wget);
|
||||
return vfs::PropertyContainer::Error;
|
||||
}
|
||||
// extract key
|
||||
sKey = vfs::trimString(readStr,0,iEqual-1);
|
||||
// extract value
|
||||
EOperation op = vfs::PropertyContainer::Set;
|
||||
if( readStr.at(iEqual) == L'+' )
|
||||
{
|
||||
if( (iEqual+1) < readStr.size() && (readStr.at(iEqual+1) == L'=') )
|
||||
{
|
||||
iEqual += 1;
|
||||
op = vfs::PropertyContainer::Add;
|
||||
}
|
||||
}
|
||||
sValue = vfs::trimString(readStr,iEqual+1,readStr.size());
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
bool vfs::PropertyContainer::initFromIniFile(vfs::Path const& sFileName)
|
||||
{
|
||||
// try to open via VirtualFileSystem
|
||||
if(getVFS()->fileExists(sFileName))
|
||||
{
|
||||
return initFromIniFile(getVFS()->getReadFile(sFileName));
|
||||
}
|
||||
else
|
||||
{
|
||||
vfs::CFile file(sFileName);
|
||||
if(file.openRead())
|
||||
{
|
||||
return initFromIniFile(vfs::tReadableFile::cast(&file));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::initFromIniFile(vfs::tReadableFile *pFile)
|
||||
{
|
||||
if(!pFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sBuffer;
|
||||
vfs::String::str_t sCurrentSection;
|
||||
int line_counter = 0;
|
||||
CReadLine rl(*pFile);
|
||||
while(rl.getLine(sBuffer))
|
||||
{
|
||||
line_counter++;
|
||||
// very simple parsing : key = value
|
||||
if(!sBuffer.empty())
|
||||
{
|
||||
// remove leading white spaces
|
||||
::size_t iStart = sBuffer.find_first_not_of(" \t",0);
|
||||
if(iStart == std::string::npos)
|
||||
{
|
||||
// only white space characters
|
||||
continue;
|
||||
}
|
||||
char first = sBuffer.at(iStart);
|
||||
switch(first)
|
||||
{
|
||||
case '!':
|
||||
case ';':
|
||||
case '#':
|
||||
// comment -> do nothing
|
||||
break;
|
||||
case '[':
|
||||
{
|
||||
vfs::String u8s;
|
||||
try
|
||||
{
|
||||
vfs::String::as_utf16(sBuffer.substr(iStart, sBuffer.length()-iStart), u8s.r_wcs());
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW( _BS(L"Conversion error in file \"") << pFile->getPath()
|
||||
<< L"\", line " << line_counter << _BS::wget, ex);
|
||||
}
|
||||
if(this->extractSection(u8s.c_wcs(), 0, sCurrentSection))
|
||||
{
|
||||
m_mapProps[sCurrentSection];
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_LOG_WARNING(_BS("WARNING : could not extract section name : ") << sBuffer << _BS::wget);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// probably key-value pair
|
||||
vfs::String::str_t u8s;
|
||||
try
|
||||
{
|
||||
vfs::String::as_utf16(sBuffer.substr(iStart, sBuffer.length()-iStart), u8s);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW( _BS(L"Conversion error in file \"") << pFile->getPath()
|
||||
<< L"\", line " << line_counter << _BS::wget, ex);
|
||||
}
|
||||
vfs::String::str_t sKey, sValue;
|
||||
EOperation op = this->extractKeyValue(u8s, 0, sKey, sValue);
|
||||
if(op != Error)
|
||||
{
|
||||
// add key-value pair to map
|
||||
if(m_mapProps.find(sCurrentSection) != m_mapProps.end())
|
||||
{
|
||||
if(op == Set)
|
||||
{
|
||||
this->section(sCurrentSection).value(sKey) = sValue;
|
||||
}
|
||||
else if(op == Add)
|
||||
{
|
||||
this->section(sCurrentSection).add(sKey, sValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VFS_LOG_WARNING(_BS(L"ERROR : could not find section [") << sCurrentSection
|
||||
<< L"] in container" << _BS::wget);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}; // end switch
|
||||
} // end if (empty)
|
||||
} // end while(!eof)
|
||||
return true;
|
||||
}
|
||||
|
||||
static vfs::UByte utf8bom[4] = {0xef,0xbb,0xbf,0x0};
|
||||
|
||||
bool vfs::PropertyContainer::writeToIniFile(vfs::Path const& sFilename, bool bCreateNew)
|
||||
{
|
||||
#ifdef WIN32
|
||||
const char ENDL[] = "\r\n";
|
||||
#else
|
||||
const char ENDL[] = "\n";
|
||||
#endif
|
||||
if(bCreateNew)
|
||||
{
|
||||
vfs::tWritableFile* file;
|
||||
bool delete_file = false;
|
||||
try
|
||||
{
|
||||
vfs::COpenWriteFile wfile(sFilename,true,true);
|
||||
file = &wfile.file();
|
||||
wfile.release();
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_LOG_WARNING(ex.what());
|
||||
// vfs not initialized?
|
||||
vfs::CFile* cfile = new vfs::CFile(sFilename);
|
||||
cfile->openWrite(true,true);
|
||||
file = vfs::tWritableFile::cast(cfile);
|
||||
delete_file = true;
|
||||
}
|
||||
tSections::iterator sit = m_mapProps.begin();
|
||||
std::stringstream ss;
|
||||
std::string str;
|
||||
ss << (char*)utf8bom;
|
||||
for(; sit != m_mapProps.end(); ++sit)
|
||||
{
|
||||
ss.str("");
|
||||
ss << "[" << sit->first.utf8() << "]" << ENDL;
|
||||
str = ss.str();
|
||||
file->write(str.c_str(), str.length());
|
||||
|
||||
ss.clear();
|
||||
ss.str("");
|
||||
Section& section = sit->second;
|
||||
section.print(ss);
|
||||
ss << ENDL;
|
||||
str = ss.str();
|
||||
file->write(str.c_str(),str.length());
|
||||
}
|
||||
file->close();
|
||||
if(delete_file)
|
||||
{
|
||||
delete file;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to open via VirtualFileSystem
|
||||
vfs::CBufferFile rfile;
|
||||
if(getVFS()->fileExists(sFilename))
|
||||
{
|
||||
vfs::COpenReadFile rf(sFilename);
|
||||
rfile.copyToBuffer(rf.file());
|
||||
}
|
||||
else if(getVFS()->createNewFile(sFilename))
|
||||
{
|
||||
vfs::tReadableFile* pFile = getVFS()->getReadFile(sFilename);
|
||||
if(pFile && pFile->openRead())
|
||||
{
|
||||
rfile.copyToBuffer(*pFile);
|
||||
pFile->close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// file doesn't exist or VFS not initialized yet
|
||||
vfs::CFile file(sFilename);
|
||||
rfile.copyToBuffer(*vfs::tReadableFile::cast(&file));
|
||||
}
|
||||
std::stringstream outbuffer;
|
||||
|
||||
std::string sBuffer;
|
||||
vfs::String::str_t sCurrentSection;
|
||||
|
||||
std::set<vfs::String> setKeys;
|
||||
std::set<vfs::String> setSections;
|
||||
tSections::iterator sit = m_mapProps.begin();
|
||||
for(; sit != m_mapProps.end(); ++sit)
|
||||
{
|
||||
setSections.insert(sit->first);
|
||||
}
|
||||
|
||||
CReadLine rl(*vfs::tReadableFile::cast(&rfile));
|
||||
outbuffer << (char*)(utf8bom);
|
||||
vfs::UInt32 line_counter = 0;
|
||||
while(rl.getLine(sBuffer))
|
||||
{
|
||||
line_counter++;
|
||||
if(!sBuffer.empty())
|
||||
{
|
||||
// remove leading white spaces
|
||||
::size_t iStart = sBuffer.find_first_not_of(" \t",0);
|
||||
char first = sBuffer.at(iStart);
|
||||
switch(first)
|
||||
{
|
||||
case '!':
|
||||
case ';':
|
||||
case '#':
|
||||
outbuffer << sBuffer << ENDL;
|
||||
break;
|
||||
case '[':
|
||||
{
|
||||
vfs::String u8s;
|
||||
try
|
||||
{
|
||||
vfs::String::as_utf16(sBuffer.substr(iStart, sBuffer.length()-iStart), u8s.r_wcs());
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(_BS(L"Conversion error in file \"") << sFilename
|
||||
<< L"\", line " << line_counter << _BS::wget, ex);
|
||||
}
|
||||
vfs::String::str_t oldSection = sCurrentSection;
|
||||
if(this->extractSection(u8s.c_wcs(), 0, sCurrentSection))
|
||||
{
|
||||
if(setSections.find(sCurrentSection) == setSections.end())
|
||||
{
|
||||
// section already handled ?!?!?!
|
||||
// just print duplicate version
|
||||
outbuffer << vfs::String::as_utf8(sBuffer) << ENDL;
|
||||
break;
|
||||
}
|
||||
if(!setKeys.empty())
|
||||
{
|
||||
// there are new keys in the previous section
|
||||
Section& oldsec = m_mapProps[oldSection];
|
||||
|
||||
std::set<vfs::String>::iterator kit = setKeys.begin();
|
||||
for(; kit != setKeys.end(); ++kit)
|
||||
{
|
||||
outbuffer << vfs::String::as_utf8(*kit) << " = " << vfs::String::as_utf8(oldsec.value(*kit)) << ENDL;
|
||||
}
|
||||
// all remaining keys were written, clear set
|
||||
setKeys.clear();
|
||||
outbuffer << ENDL;
|
||||
}
|
||||
Section& sec = m_mapProps[sCurrentSection];
|
||||
Section::tProps::iterator it = sec.mapProps.begin();
|
||||
for(; it != sec.mapProps.end(); ++it)
|
||||
{
|
||||
setKeys.insert(it->first);
|
||||
}
|
||||
}
|
||||
outbuffer << vfs::String::as_utf8(sBuffer) << ENDL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// probably key-value pair
|
||||
vfs::String u8s;
|
||||
try
|
||||
{
|
||||
vfs::String::as_utf16(sBuffer.substr(iStart, sBuffer.length()-iStart), u8s.r_wcs());
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_RETHROW(_BS(L"Conversion error in file \"") << sFilename
|
||||
<< L"\", line " << line_counter << _BS::wget, ex);
|
||||
}
|
||||
vfs::String::str_t sKey, sValue;
|
||||
if(this->extractKeyValue(u8s.c_wcs(), 0, sKey, sValue))
|
||||
{
|
||||
if(setKeys.find(sKey) != setKeys.end())
|
||||
{
|
||||
outbuffer << vfs::String::as_utf8(sKey) << " = " << vfs::String::as_utf8(m_mapProps[sCurrentSection].value(sKey)) << "\r\n";
|
||||
setKeys.erase(sKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
outbuffer << vfs::String::as_utf8(sBuffer) << ENDL;
|
||||
}
|
||||
if(setKeys.empty())
|
||||
{
|
||||
setSections.erase(sCurrentSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}; // end switch
|
||||
}
|
||||
else
|
||||
{
|
||||
outbuffer << ENDL;
|
||||
}
|
||||
}
|
||||
if(!setKeys.empty())
|
||||
{
|
||||
Section& sec = m_mapProps[sCurrentSection];
|
||||
std::set<vfs::String>::iterator kit = setKeys.begin();
|
||||
for(; kit != setKeys.end(); ++kit)
|
||||
{
|
||||
outbuffer << vfs::String::as_utf8(*kit) << " = " << vfs::String::as_utf8(sec.value(*kit)) << ENDL;
|
||||
}
|
||||
setKeys.clear();
|
||||
if(setKeys.empty())
|
||||
{
|
||||
setSections.erase(sCurrentSection);
|
||||
}
|
||||
}
|
||||
std::set<vfs::String>::iterator it = setSections.begin();
|
||||
for(; it != setSections.end(); ++it)
|
||||
{
|
||||
outbuffer << ENDL << "[" << vfs::String::as_utf8(*it) << "]" << ENDL;
|
||||
std::stringstream ss;
|
||||
m_mapProps[*it].print(outbuffer);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
vfs::COpenWriteFile wfile(sFilename,true,true);
|
||||
wfile->write(outbuffer.str().c_str(),(vfs::size_t)outbuffer.str().length());
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
VFS_LOG_WARNING(ex.what());
|
||||
vfs::CFile file(sFilename);
|
||||
if(file.openWrite(true,true))
|
||||
{
|
||||
file.write(outbuffer.str().c_str(),(vfs::size_t)outbuffer.str().length());
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void vfs::PropertyContainer::printProperties(std::ostream &out)
|
||||
{
|
||||
tSections::iterator pit = m_mapProps.begin();
|
||||
for(;pit != m_mapProps.end(); ++pit)
|
||||
{
|
||||
out << "[" << pit->first.utf8() << "]\n";
|
||||
pit->second.print(out, L" ");
|
||||
out << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vfs::PropertyContainer::Section& vfs::PropertyContainer::section(vfs::String const& sSection)
|
||||
{
|
||||
return m_mapProps[sSection];
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getValueForKey(vfs::String const& sSection, vfs::String const& sKey, vfs::String &sValue)
|
||||
{
|
||||
tSections::iterator pit = m_mapProps.find(vfs::trimString(sSection,0,(vfs::size_t)sSection.length()));
|
||||
if( pit != m_mapProps.end() )
|
||||
{
|
||||
return pit->second.value( vfs::trimString(sKey,0,(vfs::size_t)sKey.length()), sValue );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::hasProperty(vfs::String const& sSection, vfs::String const& sKey)
|
||||
{
|
||||
tSections::iterator pit = m_mapProps.find(vfs::trimString(sSection,0,(vfs::size_t)sSection.length()));
|
||||
if( pit != m_mapProps.end() )
|
||||
{
|
||||
return pit->second.has(vfs::trimString(sKey,0,sKey.length()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs::String const& vfs::PropertyContainer::getStringProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::String const& sDefaultValue)
|
||||
{
|
||||
vfs::PropertyContainer::tSections::iterator sit = m_mapProps.find(sSection);
|
||||
if(sit != m_mapProps.end())
|
||||
{
|
||||
vfs::PropertyContainer::Section::tProps::iterator pit = sit->second.mapProps.find(sKey);
|
||||
if(pit != sit->second.mapProps.end())
|
||||
{
|
||||
return pit->second;
|
||||
}
|
||||
}
|
||||
return sDefaultValue;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getStringProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::String& sValue, vfs::String const& sDefaultValue)
|
||||
{
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
sValue = sDefaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getStringProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::String::char_t* sValue, vfs::size_t len, vfs::String const& sDefaultValue)
|
||||
{
|
||||
vfs::String s;
|
||||
if(getValueForKey(sSection,sKey,s))
|
||||
{
|
||||
vfs::size_t l = std::min<vfs::size_t>(s.length(), len-1);
|
||||
wcsncpy(sValue,s.c_str(), l);
|
||||
sValue[l] = 0;
|
||||
return true;
|
||||
}
|
||||
vfs::size_t l = std::min<vfs::size_t>(sDefaultValue.length(), len-1);
|
||||
wcsncpy(sValue,sDefaultValue.c_str(), l);
|
||||
sValue[l] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs::Int64 vfs::PropertyContainer::getIntProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::Int64 iDefaultValue, vfs::Int64 iMinValue, vfs::Int64 iMaxValue)
|
||||
{
|
||||
return std::min<vfs::Int64>(iMaxValue, std::max<vfs::Int64>(iMinValue, this->getIntProperty(sSection, sKey, iDefaultValue)));
|
||||
}
|
||||
|
||||
vfs::Int64 vfs::PropertyContainer::getIntProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::Int64 iDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::Int64 iRetVal;
|
||||
if(convertTo<vfs::Int64>(sValue,iRetVal))
|
||||
{
|
||||
return iRetVal;
|
||||
}
|
||||
}
|
||||
return iDefaultValue;
|
||||
}
|
||||
|
||||
vfs::UInt64 vfs::PropertyContainer::getUIntProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::UInt64 iDefaultValue, vfs::UInt64 iMinValue, vfs::UInt64 iMaxValue)
|
||||
{
|
||||
return std::min<vfs::UInt64>(iMaxValue, std::max<vfs::UInt64>(iMinValue, this->getIntProperty(sSection, sKey, iDefaultValue)));
|
||||
}
|
||||
|
||||
vfs::UInt64 vfs::PropertyContainer::getUIntProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::UInt64 iDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::UInt64 iRetVal;
|
||||
if(convertTo<vfs::UInt64>(sValue,iRetVal))
|
||||
{
|
||||
return iRetVal;
|
||||
}
|
||||
}
|
||||
return iDefaultValue;
|
||||
}
|
||||
|
||||
double vfs::PropertyContainer::getFloatProperty(vfs::String const& sSection, vfs::String const& sKey, double fDefaultValue, double fMinValue, double fMaxValue)
|
||||
{
|
||||
return std::min<double>(fMaxValue, std::max<double>(fMinValue, this->getFloatProperty(sSection, sKey, fDefaultValue)));
|
||||
}
|
||||
|
||||
double vfs::PropertyContainer::getFloatProperty(vfs::String const& sSection, vfs::String const& sKey, double fDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
double fRetVal;
|
||||
if(convertTo<double>(sValue,fRetVal))
|
||||
{
|
||||
return fRetVal;
|
||||
}
|
||||
}
|
||||
return fDefaultValue;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getBoolProperty(vfs::String const& sSection, vfs::String const& sKey, bool bDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::Int32 iRetVal;
|
||||
if( StrCmp::Equal(sValue,L"true") || ( convertTo<>(sValue,iRetVal) && (iRetVal != 0) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if( StrCmp::Equal(sValue,"false") || ( convertTo<>(sValue,iRetVal) && (iRetVal == 0) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// else return bDefaultValue
|
||||
}
|
||||
return bDefaultValue;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getStringListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<vfs::String> &lValueList, vfs::String sDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
CTokenizer splitter(sValue);
|
||||
vfs::String entry;
|
||||
while( splitter.next(entry, L',') )
|
||||
{
|
||||
lValueList.push_back(vfs::trimString(entry,0,entry.length()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getIntListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<vfs::Int64> &lValueList, vfs::Int64 iDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::String entry;
|
||||
CTokenizer splitter(sValue);
|
||||
while( splitter.next(entry, L',') )
|
||||
{
|
||||
vfs::Int64 iRetVal;
|
||||
if(convertTo<vfs::Int64>(entry,iRetVal))
|
||||
{
|
||||
lValueList.push_back(iRetVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
lValueList.push_back(iDefaultValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getUIntListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<vfs::UInt64> &lValueList, vfs::UInt64 iDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::String entry;
|
||||
CTokenizer splitter(sValue);
|
||||
while( splitter.next(entry, L',') )
|
||||
{
|
||||
vfs::UInt64 iRetVal;
|
||||
if(convertTo<vfs::UInt64>(entry,iRetVal))
|
||||
{
|
||||
lValueList.push_back(iRetVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
lValueList.push_back(iDefaultValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool vfs::PropertyContainer::getFloatListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<double> &lValueList, double fDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::String entry;
|
||||
CTokenizer splitter(sValue);
|
||||
while( splitter.next(entry, L',') )
|
||||
{
|
||||
double fRetVal;
|
||||
if(convertTo<double>(entry,fRetVal))
|
||||
{
|
||||
lValueList.push_back(fRetVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
lValueList.push_back(fDefaultValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfs::PropertyContainer::getBoolListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<bool> &lValueList, bool bDefaultValue)
|
||||
{
|
||||
vfs::String sValue;
|
||||
if(getValueForKey(sSection,sKey,sValue))
|
||||
{
|
||||
vfs::String entry;
|
||||
CTokenizer splitter(sValue);
|
||||
while( splitter.next(entry, L',') )
|
||||
{
|
||||
vfs::Int32 iRetVal;
|
||||
if( StrCmp::Equal(entry,L"true") || ( convertTo<>(entry,iRetVal) && (iRetVal != 0) ) )
|
||||
{
|
||||
lValueList.push_back(true);
|
||||
}
|
||||
else if( StrCmp::Equal(entry,L"false") || ( convertTo<>(entry,iRetVal) && (iRetVal == 0) ) )
|
||||
{
|
||||
lValueList.push_back(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
lValueList.push_back(bDefaultValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::setStringProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::String const& sValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = sValue;
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::setIntProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::Int64 const& iValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toString<wchar_t,vfs::Int64>(iValue);
|
||||
}
|
||||
void vfs::PropertyContainer::setUIntProperty(vfs::String const& sSection, vfs::String const& sKey, vfs::UInt64 const& iValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toString<wchar_t,vfs::UInt64>(iValue);
|
||||
}
|
||||
void vfs::PropertyContainer::setFloatProperty(vfs::String const& sSection, vfs::String const& sKey, double const& fValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toString<wchar_t,double>(fValue);
|
||||
}
|
||||
void vfs::PropertyContainer::setBoolProperty(vfs::String const& sSection, vfs::String const& sKey, bool const& bValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toString<wchar_t,bool>(bValue);
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::setStringListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<vfs::String> const& slValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toStringList<vfs::String>(slValue);
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::setIntListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<vfs::Int64> const& ilValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toStringList<vfs::Int64>(ilValue);
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::setFloatListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<double> const& flValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toStringList<double>(flValue);
|
||||
}
|
||||
|
||||
void vfs::PropertyContainer::setBoolListProperty(vfs::String const& sSection, vfs::String const& sKey, std::list<bool> const& blValue)
|
||||
{
|
||||
this->section(sSection).value(sKey) = toStringList<bool>(blValue);
|
||||
}
|
||||
|
||||
/**************************************************************************************************/
|
||||
/**************************************************************************************************/
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* bfVFS : vfs/Tools/vfs_tools.cpp
|
||||
* - simple from/to string (list) conversion functions,
|
||||
* - remove leading/trailing whitspace characters in a string
|
||||
*
|
||||
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
|
||||
*
|
||||
* This file is part of the bfVFS library
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <vfs/Tools/vfs_tools.h>
|
||||
|
||||
template<>
|
||||
vfs::String vfs::toStringList<vfs::String>(std::list<vfs::String> const& rValList)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
std::list<vfs::String>::const_iterator cit = rValList.begin();
|
||||
if(cit != rValList.end())
|
||||
{
|
||||
ss << (*cit);
|
||||
cit++;
|
||||
for(;cit != rValList.end(); ++cit)
|
||||
{
|
||||
ss << L" , " << (*cit);
|
||||
}
|
||||
}
|
||||
if(!ss)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
template<>
|
||||
std::string vfs::trimString<std::string>(std::string const& sStr, vfs::size_t iMinPos, vfs::size_t iMaxPos)
|
||||
{
|
||||
if(iMinPos > iMaxPos || iMaxPos == vfs::npos)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
::size_t iStart,iEnd;
|
||||
iStart = sStr.find_first_not_of(" \t\r\n",(::size_t)iMinPos);
|
||||
iEnd = sStr.find_last_not_of(" \t\r\n",(::size_t)iMaxPos);
|
||||
if( (iStart != std::string::npos) && (iEnd != std::string::npos) )
|
||||
{
|
||||
return sStr.substr(iStart,iEnd-iStart+1);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
template<>
|
||||
std::wstring vfs::trimString<std::wstring>(std::wstring const& sStr, vfs::size_t iMinPos, vfs::size_t iMaxPos)
|
||||
{
|
||||
if(iMinPos > iMaxPos || iMaxPos == vfs::npos)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
::size_t iStart,iEnd;
|
||||
iStart = sStr.find_first_not_of(L" \t\r\n",(::size_t)iMinPos);
|
||||
iEnd = sStr.find_last_not_of(L" \t\r\n",(::size_t)iMaxPos);
|
||||
if( (iStart != std::wstring::npos) && (iEnd != std::wstring::npos) )
|
||||
{
|
||||
return sStr.substr(iStart,iEnd-iStart+1);
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
template<>
|
||||
vfs::String vfs::trimString<vfs::String>(vfs::String const& sStr, vfs::size_t iMinPos, vfs::size_t iMaxPos)
|
||||
{
|
||||
return vfs::trimString(sStr.c_wcs(), iMinPos, iMaxPos);
|
||||
}
|
||||
Reference in New Issue
Block a user