Files
Leviathan/Library/Internal/source/kfile/KFileManager.cpp
T
2026-06-01 12:46:52 +02:00

470 lines
11 KiB
C++

#include "../../include/kfile/KFileManager.h"
#include "../../include/kfile/IFileSystem.h"
#include "../../include/kfile/KStream.h"
#include "../../include/toolkit/ILock.h"
#include "../../include/toolkit/nsl.h"
#include "../../include/toolkit/nsluni.h"
#include <windows.h>
#include "../../include/toolkit/SafeTickCount.h"
// 2010.04.29 - prodongi
#include "../../include/compress/XZip.h"
//#include "SDebug_Util.h"
static XCriticalSection s_lock;
KFileManager & KFileManager::Instance()
{
s_lock.Lock();
static KFileManager _inst;
s_lock.UnLock();
return _inst;
}
// 2010.04.29 - prodongi
KFileManager::KFileManager() : m_xzipBuffer(NULL)
{
}
KFileManager::~KFileManager()
{
// 2010.04.29 - prodongi
if (m_xzipBuffer)
free(m_xzipBuffer);
}
KStream * getFileFromSourceList( KFileSystem* & pFileSystem, const std::vector< struct KFileSystem* > & vSourceList, const char *szReourceName )
{
KStream * pFile = NULL;
std::vector< struct KFileSystem* >::const_iterator it;
for( it = vSourceList.begin(); it != vSourceList.end(); ++it )
{
pFileSystem = (*it);
if( pFileSystem )
pFile = pFileSystem->open( szReourceName, KFileSystem::READ_ONLY );
if( pFile ) break;
}
return pFile;
}
void KFileManager::AddResourceSource( struct KFileSystem *pFileSystem )
{
THREAD_SYNCRONIZE( m_lckIntf );
m_vSourceList.push_back( pFileSystem );
}
void KFileManager::RemoveResourceSource( struct KFileSystem *pFileSystem )
{
THREAD_SYNCRONIZE( m_lckIntf );
std::vector< struct KFileSystem* >::iterator it;
for( it = m_vSourceList.begin(); it != m_vSourceList.end(); ++it )
{
if( (*it) != pFileSystem ) continue;
m_vSourceList.erase( it );
break;
}
}
static bool getLocalizedFile( const char *szResource, std::string * strFileName )
{
const char *szEncoding = nsl::uni::get_resource_encoding(); /// 2011.06.15 듀얼 클라이언트 설정 - prodongi
if( szEncoding && szEncoding[0] && szResource[0] )
{
const char *pDot = strchr( szResource, '.' );
if( pDot )
{
(*strFileName).assign( szResource, pDot );
(*strFileName) += "(";
(*strFileName) += szEncoding;
(*strFileName) += ")";
(*strFileName) += pDot;
return true;
}
}
return false;
}
bool KFileManager::IsValidResource( const char *szResourceName )
{
// { 로컬라이즈
const char *szFileName = szResourceName;
std::string strResourceName;
bool bUseLocale = getLocalizedFile( szResourceName, &strResourceName );
if( bUseLocale ) szFileName = strResourceName.c_str();
// }
{
THREAD_SYNCRONIZE( m_lckIntf );
// 파일 열고
std::vector< struct KFileSystem* >::const_iterator it;
for( it = m_vSourceList.begin(); it != m_vSourceList.end(); ++it )
{
// if( (*it)->isFile( szResourceName ) ) return true;
if( (*it)->isFile( szResourceName ) ) // 2011.07.26 - servnates : 코드 가독성 있도록 수정
return true;
// if( szResourceName != szFileName ) if( (*it)->isFile( szFileName ) ) return true;
if( szResourceName != szFileName ) // 2011.07.26 - servnates : 코드 가독성 있도록 수정
{
if( (*it)->isFile( szFileName ) )
return true;
}
}
}
return false;
}
std::string KFileManager::CreateTemporaryFileFromResource( const char *szResourceName )
{
KStream *pFile = NULL;
{
THREAD_SYNCRONIZE( m_lckIntf );
// 파일 열고
KFileSystem *pFileSystem = NULL;
pFile = getFileFromSourceList( pFileSystem, m_vSourceList, szResourceName );
if( !pFile ) return "";
}
// 임시파일명 얻고
char szPath[512] = { 0, };
if( !GetTempPath( _countof(szPath), szPath ) ) return std::string( "./" ) + szResourceName;
std::string strFileName = szPath;
strFileName += szResourceName;
// 있던거 지우고
DeleteFile( strFileName.c_str() );
// 파일 만들자
KFileStream stream( strFileName.c_str(), KFileStream::wronly );
if( !stream.IsValid() ) return "";
// 메모리에 일단 올리고
// 2010.04.29 - prodoingi
size_t size = pFile->getOriginalSize();
char *pBuffer = new char[size ];
if( pFile->Read( pBuffer, pFile->Size() ) != size ) assert( 0 );
// 파일에 쓴 다음
stream.Write( pBuffer,size );
/*
char *pBuffer = new char[ pFile->Size() ];
if( pFile->Read( pBuffer, pFile->Size() ) != pFile->Size() ) assert( 0 );
// 파일에 쓴 다음
stream.Write( pBuffer, pFile->Size() );
*/
// 임시자료 다 지우세~
{
delete [] pBuffer;
THREAD_SYNCRONIZE( m_lckIntf );
delete pFile;
}
return strFileName;
}
// 2010.06.29 - prodongi
char* KFileManager::readData(char const* resourceName)
{
std::string strResourceName;
getLocalizedFile( resourceName, &strResourceName );
KStream *pFile = NULL;
{
THREAD_SYNCRONIZE( m_lckIntf );
// 파일 열고
KFileSystem *pFileSystem = NULL;
pFile = getFileFromSourceList( pFileSystem, m_vSourceList, strResourceName.c_str() );
if( !pFile )
{
pFile = getFileFromSourceList( pFileSystem, m_vSourceList, resourceName );
if ( !pFile )
{
return NULL;
}
}
}
size_t size = pFile->getOriginalSize();
char *pBuffer = new char[ size+1 ];
if( pFile->Read( pBuffer, pFile->Size() ) != size )
{
delete[] pBuffer;
return NULL;
}
pBuffer[size] = 0x00;
THREAD_SYNCRONIZE( m_lckIntf );
delete pFile;
return pBuffer;
}
std::string KFileManager::CreateTemporaryFileFromResourceWithLocale( const char *szResourceName )
{
std::string strResourceName;
getLocalizedFile( szResourceName, &strResourceName );
KStream *pFile = NULL;
{
THREAD_SYNCRONIZE( m_lckIntf );
// 파일 열고
KFileSystem *pFileSystem = NULL;
pFile = getFileFromSourceList( pFileSystem, m_vSourceList, strResourceName.c_str() );
if( !pFile )
{
pFile = getFileFromSourceList( pFileSystem, m_vSourceList, szResourceName );
if ( !pFile )
{
return "";
}
strResourceName = szResourceName;
}
}
// 임시파일명 얻고
char szPath[512] = { 0, };
if( !GetTempPath( _countof(szPath), szPath ) ) return std::string( "./" ) + strResourceName;
std::string strFileName = szPath;
strFileName += strResourceName;
// 있던거 지우고
DeleteFile( strFileName.c_str() );
// 파일 만들자
KFileStream stream( strFileName.c_str(), KFileStream::wronly );
if( !stream.IsValid() ) return "";
// 메모리에 일단 올리고
// 2010.04.29 - prodongi
size_t size = pFile->getOriginalSize();
char *pBuffer = new char[ size ];
if( pFile->Read( pBuffer, pFile->Size() ) != size ) assert( 0 );
// 파일에 쓴 다음
stream.Write( pBuffer, size );
/*
char *pBuffer = new char[ pFile->Size() ];
if( pFile->Read( pBuffer, pFile->Size() ) != pFile->Size() ) assert( 0 );
// 파일에 쓴 다음
stream.Write( pBuffer, pFile->Size() );
*/
// 임시자료 다 지우세~
{
delete [] pBuffer;
THREAD_SYNCRONIZE( m_lckIntf );
delete pFile;
}
return strFileName;
}
std::string KFileManager::GetFullPathNameFromResource( const char *szResourceName )
{
THREAD_SYNCRONIZE( m_lckIntf );
std::string strString;
std::vector< struct KFileSystem* >::const_iterator it;
for( it = m_vSourceList.begin(); it != m_vSourceList.end(); ++it )
{
strString = (*it)->getFullPathName( szResourceName );
if( !strString.empty() ) return strString;
}
return "";
}
void KFileManager::RemoveAllStream()
{
THREAD_SYNCRONIZE( m_lckIntf );
bool bResult;
KHash< StreamCache, hashPr_string_nocase >::node* _node = NULL;
std::vector< std::string > vDeleteList;
bResult = m_hsStreamCacheByName.get_first_node( _node );
while( bResult )
{
vDeleteList.push_back( _node->key.m_pStr );
bResult = m_hsStreamCacheByName.get_next_node( _node );
}
for( std::vector< std::string >::iterator it = vDeleteList.begin(); it != vDeleteList.end(); ++it )
{
StreamCache tmp;
if( m_hsStreamCacheByName.lookup( *it, tmp ) )
{
delete tmp.pStream;
}
m_hsStreamCacheByName.erase( *it );
}
}
void KFileManager::RemoveUnnecessaryStream()
{
THREAD_SYNCRONIZE( m_lckIntf );
const DWORD STREAM_EXPIRE_TIME = 600000; // 10분 지나면 삭제
DWORD dwTime = GetSafeTickCount();
bool bResult;
KHash< StreamCache, hashPr_string_nocase >::node* _node = NULL;
std::vector< std::string > vDeleteList;
bResult = m_hsStreamCacheByName.get_first_node( _node );
while( bResult )
{
if( _node->value.dwLastUse + STREAM_EXPIRE_TIME < dwTime ) vDeleteList.push_back( _node->key.m_pStr );
bResult = m_hsStreamCacheByName.get_next_node( _node );
}
for( std::vector< std::string >::iterator it = vDeleteList.begin(); it != vDeleteList.end(); ++it )
{
_oprint( "DELETE STREAM CACHE : %s\n", (*it).c_str() );
StreamCache tmp;
if( m_hsStreamCacheByName.lookup( *it, tmp ) )
{
delete tmp.pStream;
}
m_hsStreamCacheByName.erase( *it );
}
}
class KStream* KFileManager::CreateStreamFromResource( const char *szResourceName, bool bCache )
{
if( szResourceName[0] == NULL ) return NULL;
THREAD_SYNCRONIZE( m_lckIntf );
{
THREAD_SYNCRONIZE( m_lckCache );
StreamCache cache;
if( m_hsStreamCacheByName.lookup( szResourceName, cache ) )
{
cache.dwLastUse = GetSafeTickCount();
return new KMemoryStream( cache.pStream->GetMappedPtr(0), cache.pStream->GetLength(), true );
}
}
// { 로컬라이즈
const char *szFileName = szResourceName;
std::string strResourceName;
bool bUseLocale = getLocalizedFile( szResourceName, &strResourceName );
if( bUseLocale ) szFileName = strResourceName.c_str();
// }
KFileSystem *pFileSystem = NULL;
// Search Localized file first, then global file
KStream *pFile = getFileFromSourceList( pFileSystem, m_vSourceList, szFileName );
if( !pFile )
{
if( szFileName != szResourceName && bUseLocale ) pFile = getFileFromSourceList( pFileSystem, m_vSourceList, szResourceName );
if( !pFile )
{
return NULL;
}
}
/*
// Search Global file first, then Localized file
KStream *pFile = getFileFromSourceList( pFileSystem, m_vSourceList, szResourceName );
if( !pFile )
{
if( szFileName != szResourceName && bUseLocale ) pFile = getFileFromSourceList( pFileSystem, m_vSourceList, szFileName );
if( !pFile )
{
return NULL;
}
}
*/
// 2010.04.29 - prodongi
KMemoryStream* pStream = new KMemoryStream( pFile->getOriginalSize() );
//KMemoryStream* pStream = new KMemoryStream( pFile->Size() );
pFile->Read( pStream->GetMappedPtr( KStream::MAPPED_WRITE ), pFile->Size() );
delete pFile;
if( bCache )
{
THREAD_SYNCRONIZE( m_lckCache );
m_hsStreamCacheByName.add( szResourceName, StreamCache( pStream, GetSafeTickCount() ) );
pStream = new KMemoryStream( pStream->GetMappedPtr(0), pStream->GetLength(), true );
}
return pStream;
}
bool KFileManager::DeleteTemporaryFile( const char *szResourceName )
{
return false;
}
bool KFileManager::DeleteStream( class KStream* pStream )
{
if( !pStream ) return false;
delete pStream;
return true;
}
void KFileManager::EraseStream( std::string* pStreamName )
{
StreamCache tmp;
if( m_hsStreamCacheByName.lookup( *pStreamName, tmp ) )
{
delete tmp.pStream;
m_hsStreamCacheByName.erase( *pStreamName );
}
}
/// @brief 2010.04.29 - prodongi
size_t KFileManager::checkXZipBufferAlloc(void* src, size_t srcSize)
{
size_t originalSize = XZip::GetOriginalSize(src, srcSize);
if (!m_xzipBuffer)
{
m_xzipBuffer = (char*)malloc(originalSize);
m_xzipBufferSize = originalSize;
}
else if (originalSize > m_xzipBufferSize)
{
char* temp = (char*)realloc(m_xzipBuffer, originalSize);
if( temp != NULL )
{
m_xzipBuffer = temp;
m_xzipBufferSize = originalSize;
}
return m_xzipBufferSize;
}
return originalSize;
}