Index: src/ch/FileFilter.cpp =================================================================== diff -u -r69b48f0b4d7fad78f95854e95fca166014311474 -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/ch/FileFilter.cpp (.../FileFilter.cpp) (revision 69b48f0b4d7fad78f95854e95fca166014311474) +++ src/ch/FileFilter.cpp (.../FileFilter.cpp) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -192,7 +192,7 @@ bool bRes=false; for(std::vector::const_iterator iterMask = m_astrMask.begin(); iterMask != m_astrMask.end(); ++iterMask) { - if(MatchMask(*iterMask, spInfo->GetFileName().ToString())) + if(MatchMask(*iterMask, spInfo->GetFullFilePath().GetFileName().ToString())) bRes = true; } if(!bRes) @@ -204,7 +204,7 @@ { for(std::vector::const_iterator iterExcludeMask = m_astrExcludeMask.begin(); iterExcludeMask != m_astrExcludeMask.end(); ++iterExcludeMask) { - if(MatchMask(*iterExcludeMask, spInfo->GetFileName().ToString())) + if(MatchMask(*iterExcludeMask, spInfo->GetFullFilePath().GetFileName().ToString())) return false; } } Index: src/ch/FileInfo.cpp =================================================================== diff -u -r3f33c90e9e49ccf7b52b604e849ba8be5be1dba7 -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/ch/FileInfo.cpp (.../FileInfo.cpp) (revision 3f33c90e9e49ccf7b52b604e849ba8be5be1dba7) +++ src/ch/FileInfo.cpp (.../FileInfo.cpp) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -100,7 +100,7 @@ // add data to members chcore::TSmartPath pathNew(pathFile); - pathNew.DeleteLastComponent(); + pathNew.DeleteFileName(); Create(&wfd, pathNew, stSrcIndex); return true; @@ -119,93 +119,6 @@ } } -chcore::TSmartPath CFileInfo::GetFileDrive() const -{ - BOOST_ASSERT(m_pBasePaths); - if(!m_pBasePaths) - THROW(_T("Invalid pointer"), 0, 0, 0); - - chcore::TSmartPath pathCombined = (m_stSrcIndex != std::numeric_limits::max()) ? m_pBasePaths->GetAt(m_stSrcIndex) + m_pathFile : m_pathFile; - - TCHAR szDrive[_MAX_DRIVE]; - _tsplitpath(pathCombined.ToString(), szDrive, NULL, NULL, NULL); - return chcore::PathFromString(szDrive); -} - -chcore::TSmartPath CFileInfo::GetFileDir() const -{ - BOOST_ASSERT(m_pBasePaths); - if(!m_pBasePaths) - THROW(_T("Invalid pointer"), 0, 0, 0); - - chcore::TSmartPath pathCombined = (m_stSrcIndex != std::numeric_limits::max()) ? m_pBasePaths->GetAt(m_stSrcIndex) + m_pathFile : m_pathFile; - - TCHAR szDir[_MAX_DIR]; - _tsplitpath(pathCombined.ToString(), NULL, szDir, NULL, NULL); - return chcore::PathFromString(szDir); -} - -chcore::TSmartPath CFileInfo::GetFileTitle() const -{ - BOOST_ASSERT(m_pBasePaths); - if(!m_pBasePaths) - THROW(_T("Invalid pointer"), 0, 0, 0); - - chcore::TSmartPath pathCombined = (m_stSrcIndex != std::numeric_limits::max()) ? m_pBasePaths->GetAt(m_stSrcIndex) + m_pathFile : m_pathFile; - TCHAR szName[_MAX_FNAME]; - _tsplitpath(pathCombined.ToString(), NULL, NULL, szName, NULL); - return chcore::PathFromString(szName); -} - -chcore::TSmartPath CFileInfo::GetFileExt() const -{ - ASSERT(m_pBasePaths); - BOOST_ASSERT(m_pBasePaths); - if(!m_pBasePaths) - THROW(_T("Invalid pointer"), 0, 0, 0); - - chcore::TSmartPath pathCombined = (m_stSrcIndex != std::numeric_limits::max()) ? m_pBasePaths->GetAt(m_stSrcIndex) + m_pathFile : m_pathFile; - TCHAR szExt[_MAX_EXT]; - _tsplitpath(pathCombined.ToString(), NULL, NULL, NULL, szExt); - return chcore::PathFromString(szExt); -} - -chcore::TSmartPath CFileInfo::GetFileRoot() const -{ - ASSERT(m_pBasePaths); - BOOST_ASSERT(m_pBasePaths); - if(!m_pBasePaths) - THROW(_T("Invalid pointer"), 0, 0, 0); - - chcore::TSmartPath pathCombined = (m_stSrcIndex != std::numeric_limits::max()) ? m_pBasePaths->GetAt(m_stSrcIndex) + m_pathFile : m_pathFile; - - TCHAR szDrive[_MAX_DRIVE]; - TCHAR szDir[_MAX_DIR]; - _tsplitpath(pathCombined.ToString(), szDrive, szDir, NULL, NULL); - return chcore::PathFromString(szDrive) + chcore::PathFromString(szDir); -} - -chcore::TSmartPath CFileInfo::GetFileName() const -{ - BOOST_ASSERT(m_pBasePaths); - if(!m_pBasePaths) - THROW(_T("Invalid pointer"), 0, 0, 0); - - chcore::TSmartPath pathCombined; - if(m_pBasePaths && m_stSrcIndex != std::numeric_limits::max()) - pathCombined = m_pBasePaths->GetAt(m_stSrcIndex) + m_pathFile; - else - { - ASSERT(m_stSrcIndex == std::numeric_limits::max()); - pathCombined = m_pathFile; - } - - TCHAR szName[_MAX_FNAME]; - TCHAR szExt[_MAX_EXT]; - _tsplitpath(pathCombined.ToString(), NULL, NULL, szName, szExt); - return chcore::PathFromString(szName) + chcore::PathFromString(szExt); -} - bool CFileInfo::operator==(const CFileInfo& rInfo) { return (rInfo.m_dwAttributes == m_dwAttributes && rInfo.m_ftCreation.dwHighDateTime == m_ftCreation.dwHighDateTime && rInfo.m_ftCreation.dwLowDateTime == m_ftCreation.dwLowDateTime Index: src/ch/FileInfo.h =================================================================== diff -u -r3f33c90e9e49ccf7b52b604e849ba8be5be1dba7 -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/ch/FileInfo.h (.../FileInfo.h) (revision 3f33c90e9e49ccf7b52b604e849ba8be5be1dba7) +++ src/ch/FileInfo.h (.../FileInfo.h) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -43,16 +43,8 @@ ULONGLONG GetLength64() const { return m_uhFileSize; } void SetLength64(ULONGLONG uhSize) { m_uhFileSize=uhSize; } - chcore::TSmartPath GetFileDrive() const; // returns string with src disk - - chcore::TSmartPath GetFileDir() const; // @rdesc Returns \WINDOWS\ for C:\WINDOWS\WIN.INI - chcore::TSmartPath GetFileTitle() const; // @cmember returns WIN for C:\WINDOWS\WIN.INI - chcore::TSmartPath GetFileExt() const; /** @cmember returns INI for C:\WINDOWS\WIN.INI */ - chcore::TSmartPath GetFileRoot() const; /** @cmember returns C:\WINDOWS\ for C:\WINDOWS\WIN.INI */ - chcore::TSmartPath GetFileName() const; /** @cmember returns WIN.INI for C:\WINDOWS\WIN.INI */ - const chcore::TSmartPath& GetFilePath() const { return m_pathFile; } // returns path with m_pathFile (probably not full) - chcore::TSmartPath GetFullFilePath() const; /** @cmember returns C:\WINDOWS\WIN.INI for C:\WINDOWS\WIN.INI */ + chcore::TSmartPath GetFullFilePath() const; // returns full path void SetFilePath(const chcore::TSmartPath& tPath) { m_pathFile = tPath; }; /* Get File times info (equivalent to CFindFile members) */ Index: src/ch/TTaskDefinition.cpp =================================================================== diff -u -r69b48f0b4d7fad78f95854e95fca166014311474 -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/ch/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision 69b48f0b4d7fad78f95854e95fca166014311474) +++ src/ch/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -104,7 +104,7 @@ void TTaskDefinition::SetDestinationPath(const chcore::TSmartPath& pathDestination) { m_pathDestinationPath = pathDestination; - m_pathDestinationPath.AppendIfNotExists(_T("\\"), false); + m_pathDestinationPath.AppendSeparatorIfDoesNotExist(); m_bModified = true; } @@ -181,7 +181,7 @@ if(!tTaskInfo.GetValue(_T("TaskDefinition.DestinationPath"), m_pathDestinationPath) || m_pathDestinationPath.IsEmpty()) THROW(_T("Missing destination path"), 0, 0, 0); - m_pathDestinationPath.AppendIfNotExists(_T("\\"), false); + m_pathDestinationPath.AppendSeparatorIfDoesNotExist(); int iOperation = eOperation_None; if(!tTaskInfo.GetValue(_T("TaskDefinition.OperationType"), iOperation)) Index: src/ch/task.cpp =================================================================== diff -u -r3f33c90e9e49ccf7b52b604e849ba8be5be1dba7 -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/ch/task.cpp (.../task.cpp) (revision 3f33c90e9e49ccf7b52b604e849ba8be5be1dba7) +++ src/ch/task.cpp (.../task.cpp) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -463,9 +463,6 @@ WIN32_FIND_DATA wfd; chcore::TSmartPath pathCurrent; - // append '\\' at the end of path if needed - pathDirName.AppendIfNotExists(_T("\\"), false); - pathCurrent = pathDirName + chcore::PathFromString(_T("*")); // Iterate through dirs & files @@ -778,15 +775,15 @@ size_t stCurrentIndex = m_tTaskBasicProgressInfo.GetCurrentIndex(); if(stCurrentIndex < m_files.GetSize()) - pData->m_strPath = m_files.GetAt(stCurrentIndex)->GetFileName().ToString(); + pData->m_strPath = m_files.GetAt(stCurrentIndex)->GetFullFilePath().GetFileName().ToString(); else { if(m_files.GetSize() > 0) - pData->m_strPath = m_files.GetAt(0)->GetFileName().ToString(); + pData->m_strPath = m_files.GetAt(0)->GetFullFilePath().GetFileName().ToString(); else { if(m_tTaskDefinition.GetSourcePathCount() > 0) - pData->m_strPath = m_tTaskDefinition.GetSourcePathAt(0).GetLastComponent().ToString(); + pData->m_strPath = m_tTaskDefinition.GetSourcePathAt(0).GetFileName().ToString(); else pData->m_strPath.Empty(); } @@ -806,21 +803,21 @@ if(stCurrentIndex < m_files.GetSize()) { pData->m_strFullFilePath = m_files.GetAt(stCurrentIndex)->GetFullFilePath().ToString(); - pData->m_strFileName = m_files.GetAt(stCurrentIndex)->GetFileName().ToString(); + pData->m_strFileName = m_files.GetAt(stCurrentIndex)->GetFullFilePath().GetFileName().ToString(); } else { if(m_files.GetSize() > 0) { pData->m_strFullFilePath = m_files.GetAt(0)->GetFullFilePath().ToString(); - pData->m_strFileName = m_files.GetAt(0)->GetFileName().ToString(); + pData->m_strFileName = m_files.GetAt(0)->GetFullFilePath().GetFileName().ToString(); } else { if(m_tTaskDefinition.GetSourcePathCount() > 0) { pData->m_strFullFilePath = m_tTaskDefinition.GetSourcePathAt(0).ToString(); - pData->m_strFileName = m_tTaskDefinition.GetSourcePathAt(0).GetLastComponent().ToString(); + pData->m_strFileName = m_tTaskDefinition.GetSourcePathAt(0).GetFileName().ToString(); } else { @@ -1080,8 +1077,7 @@ bool bExists = spFileInfo->Create(m_tTaskDefinition.GetSourcePathAt(stIndex), stIndex); if(!bExists) { - CString strSrcFile = m_tTaskDefinition.GetSourcePathAt(stIndex).ToString(); - FEEDBACK_FILEERROR ferr = { (PCTSTR)strSrcFile, NULL, eFastMoveError, ERROR_FILE_NOT_FOUND }; + FEEDBACK_FILEERROR ferr = { m_tTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND }; CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); switch(frResult) { @@ -1122,13 +1118,13 @@ if(!m_arrSourcePathsInfo.GetAt(stIndex)->IsDestinationPathSet()) { // generate something - if dest folder == src folder - search for copy - if(m_tTaskDefinition.GetDestinationPath() == spFileInfo->GetFileRoot()) + if(m_tTaskDefinition.GetDestinationPath() == spFileInfo->GetFullFilePath().GetFileRoot()) { chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), m_tTaskDefinition.GetDestinationPath()); m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(pathSubst); } else - m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFileName()); + m_arrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName()); } // add if needed @@ -1264,8 +1260,7 @@ fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); m_log.loge(fmt); - CString strFile = spFileInfo->GetFullFilePath().ToString(); - FEEDBACK_FILEERROR ferr = { (PCTSTR)strFile, NULL, eDeleteError, dwLastError }; + FEEDBACK_FILEERROR ferr = { spFileInfo->GetFullFilePath().ToString(), NULL, eDeleteError, dwLastError }; CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)m_piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); switch(frResult) { @@ -2590,15 +2585,14 @@ chcore::TSmartPath CTask::FindFreeSubstituteName(chcore::TSmartPath pathSrcPath, chcore::TSmartPath pathDstPath) const { // get the name from srcpath - pathSrcPath.CutIfExists(_T("\\")); - pathDstPath.AppendIfNotExists(_T("\\")); + pathSrcPath.StripSeparatorAtEnd(); - chcore::TSmartPath pathLastComponent = pathSrcPath.GetLastComponent(); + chcore::TSmartPath pathFilename = pathSrcPath.GetFileName(); // set the dest path CString strCheckPath; ictranslate::CFormat fmt(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); - fmt.SetParam(_t("%name"), pathLastComponent.ToString()); + fmt.SetParam(_t("%name"), pathFilename.ToString()); chcore::TSmartPath pathCheckPath(chcore::PathFromString((PCTSTR)fmt)); // when adding to strDstPath check if the path already exists - if so - try again @@ -2607,7 +2601,7 @@ while(PathExist(pathDstPath + pathCheckPath)) { fmt.SetFormat(strFmt); - fmt.SetParam(_t("%name"), pathLastComponent.ToString()); + fmt.SetParam(_t("%name"), pathFilename.ToString()); fmt.SetParam(_t("%count"), ++iCounter); pathCheckPath.FromString((PCTSTR)fmt); } @@ -2620,22 +2614,16 @@ if(!spFileInfo) THROW(_T("Invalid pointer"), 0, 0, 0); - // add '\\' - pathDst.AppendIfNotExists(_T("\\"), false); - // iFlags: bit 0-ignore folders; bit 1-force creating directories if (iFlags & 0x02) { // force create directories - TCHAR dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; - _tsplitpath(spFileInfo->GetFullFilePath().ToString(), NULL, dir, fname, ext); + chcore::TSmartPath pathCombined = pathDst + spFileInfo->GetFullFilePath().GetFileDir(); - pathDst.CutIfExists(_T("\\"), false); - // force create directory - SHCreateDirectoryEx(NULL, CString(pathDst.ToString()) + dir, NULL); + SHCreateDirectoryEx(NULL, pathCombined.ToString(), NULL); - return pathDst + chcore::PathFromString(dir) + chcore::PathFromString(fname) + chcore::PathFromString(ext); + return pathCombined + spFileInfo->GetFullFilePath().GetFileName(); } else { @@ -2653,7 +2641,7 @@ return pathDst + m_arrSourcePathsInfo.GetAt(stSrcIndex)->GetDestinationPath() + spFileInfo->GetFilePath(); } else - return pathDst + spFileInfo->GetFileName(); + return pathDst + spFileInfo->GetFullFilePath().GetFileName(); } } @@ -2744,69 +2732,67 @@ return spPathData->GetMove(); } - void CTask::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType) { - TCHAR drv[_MAX_DRIVE+1]; + TCHAR drv[_MAX_DRIVE+1]; - _tsplitpath(spPath.ToString(), drv, NULL, NULL, NULL); - if(lstrlen(drv) != 0) - { - // add '\\' - lstrcat(drv, _T("\\")); - _tcsupr(drv); + _tsplitpath(spPath.ToString(), drv, NULL, NULL, NULL); + if(lstrlen(drv) != 0) + { + // add '\\' + lstrcat(drv, _T("\\")); + _tcsupr(drv); - // disk number - if(piDrvNum) - *piDrvNum=drv[0]-_T('A'); + // disk number + if(piDrvNum) + *piDrvNum=drv[0]-_T('A'); - // disk type - if(puiDrvType) - { - *puiDrvType=GetDriveType(drv); - if(*puiDrvType == DRIVE_NO_ROOT_DIR) - *puiDrvType=DRIVE_UNKNOWN; - } - } - else - { - // there's no disk in a path - if(piDrvNum) - *piDrvNum=-1; + // disk type + if(puiDrvType) + { + *puiDrvType=GetDriveType(drv); + if(*puiDrvType == DRIVE_NO_ROOT_DIR) + *puiDrvType=DRIVE_UNKNOWN; + } + } + else + { + // there's no disk in a path + if(piDrvNum) + *piDrvNum=-1; - if(puiDrvType) - { - // check for unc path - if(_tcsncmp(spPath.ToString(), _T("\\\\"), 2) == 0) - *puiDrvType=DRIVE_REMOTE; - else - *puiDrvType=DRIVE_UNKNOWN; - } - } + if(puiDrvType) + { + // check for unc path + if(_tcsncmp(spPath.ToString(), _T("\\\\"), 2) == 0) + *puiDrvType=DRIVE_REMOTE; + else + *puiDrvType=DRIVE_UNKNOWN; + } + } } bool CTask::PathExist(chcore::TSmartPath pathToCheck) { - WIN32_FIND_DATA fd; + WIN32_FIND_DATA fd; - // search by exact name - HANDLE hFind = FindFirstFile(pathToCheck.ToString(), &fd); - if(hFind != INVALID_HANDLE_VALUE) - return true; + // search by exact name + HANDLE hFind = FindFirstFile(pathToCheck.ToString(), &fd); + if(hFind != INVALID_HANDLE_VALUE) + return true; - // another try (add '\\' if needed and '*' for marking that we look for ie. c:\* - // instead of c:\, which would never be found prev. way) - pathToCheck.AppendIfNotExists(_T("\\"), false); - pathToCheck.AppendIfNotExists(_T("*"), false); + // another try (add '\\' if needed and '*' for marking that we look for ie. c:\* + // instead of c:\, which would never be found prev. way) + pathToCheck.AppendIfNotExists(_T("*"), false); - hFind = FindFirstFile(pathToCheck.ToString(), &fd); - if(hFind != INVALID_HANDLE_VALUE) - { - ::FindClose(hFind); - return true; - } - else - return false; + hFind = FindFirstFile(pathToCheck.ToString(), &fd); + if(hFind != INVALID_HANDLE_VALUE) + { + ::FindClose(hFind); + return true; + } + else + return false; } //////////////////////////////////////////////////////////////////////////////// Index: src/libchcore/TPath.cpp =================================================================== diff -u -r280a99da8f4dfa84ea3587c5c9df3363ac0c8f4f -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/libchcore/TPath.cpp (.../TPath.cpp) (revision 280a99da8f4dfa84ea3587c5c9df3363ac0c8f4f) +++ src/libchcore/TPath.cpp (.../TPath.cpp) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -21,6 +21,7 @@ #include "TPath.h" #include #include "../libicpf/exception.h" +#include BEGIN_CHCORE_NAMESPACE @@ -250,10 +251,23 @@ TSmartPath TSmartPath::operator+(const TSmartPath& rPath) const { TSmartPath spNewPath(*this); - if(rPath.m_pPath) + if(rPath.m_pPath && rPath.m_pPath->m_strPath.length() > 0) { spNewPath.PrepareToWrite(); - spNewPath.m_pPath->m_strPath += rPath.m_pPath->m_strPath; + + // detect separators + bool bThisEndsWithSeparator = EndsWithSeparator(); + bool bInStartsWithSeparator = rPath.StartsWithSeparator(); + + if(!bThisEndsWithSeparator && !bInStartsWithSeparator) + spNewPath.m_pPath->m_strPath += _T("\\") + rPath.m_pPath->m_strPath; + else if(bThisEndsWithSeparator ^ bInStartsWithSeparator) + spNewPath.m_pPath->m_strPath += rPath.m_pPath->m_strPath; + else + { + spNewPath.m_pPath->m_strPath.erase(m_pPath->m_strPath.length() - 1); + spNewPath.m_pPath->m_strPath += rPath.m_pPath->m_strPath; + } } return spNewPath; @@ -270,10 +284,23 @@ TSmartPath& TSmartPath::operator+=(const TSmartPath& rPath) { // if there is no path inside rPath, then there is no point in doing anything - if(rPath.m_pPath) + if(rPath.m_pPath && rPath.m_pPath->m_strPath.length() > 0) { PrepareToWrite(); - m_pPath->m_strPath += rPath.m_pPath->m_strPath; + + // detect separators + bool bThisEndsWithSeparator = EndsWithSeparator(); + bool bInStartsWithSeparator = rPath.StartsWithSeparator(); + + if(!bThisEndsWithSeparator && !bInStartsWithSeparator) + m_pPath->m_strPath += _T("\\") + rPath.m_pPath->m_strPath; + else if(bThisEndsWithSeparator ^ bInStartsWithSeparator) + m_pPath->m_strPath += rPath.m_pPath->m_strPath; + else + { + m_pPath->m_strPath.erase(m_pPath->m_strPath.length() - 1); + m_pPath->m_strPath += rPath.m_pPath->m_strPath; + } } return *this; @@ -461,31 +488,72 @@ } // ============================================================================ -/// chcore::TSmartPath::GetLastComponent -/// @date 2010/10/12 +/// chcore::TSmartPath::HasLengthExtension +/// @date 2010/10/16 /// -/// @brief Retrieves the last component of path (i.e. test.txt for c:\test\test.txt) -/// @return Sub-path with the last component. +/// @brief Checks if the path has prefix allowing handling of longer paths (\\?\) +/// @return True if prefix exists, false otherwise. // ============================================================================ -TSmartPath TSmartPath::GetLastComponent() +bool TSmartPath::HasLengthExtension() const { - if(!m_pPath) - return TSmartPath(); + return m_pPath && boost::starts_with(m_pPath->m_strPath, _T("\\\\?\\")); +} - boost::iterator_range rangeIter; - rangeIter = boost::find_last(m_pPath->m_strPath, DEFAULT_PATH_SEPARATOR); +// ============================================================================ +/// chcore::TSmartPath::AddLengthExtension +/// @date 2010/10/16 +/// +/// @brief Adds a length extension prefix if not exist. +// ============================================================================ +void TSmartPath::AddLengthExtension() +{ + if(!HasLengthExtension()) + { + PrepareToWrite(); + m_pPath->m_strPath.insert(0, _T("\\\\?\\")); + } +} - std::wstring wstrData; - wstrData.insert(wstrData.end(), rangeIter.end(), m_pPath->m_strPath.end()); - - return PathFromString(wstrData); +// ============================================================================ +/// chcore::TSmartPath::DeleteLengthExtension +/// @date 2010/10/16 +/// +/// @brief Deletes length extension prefix from path if exists. +// ============================================================================ +void TSmartPath::DeleteLengthExtension() +{ + if(HasLengthExtension()) + { + PrepareToWrite(); + m_pPath->m_strPath.erase(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + 4); + } } -bool TSmartPath::HasLengthExtension() const +// ============================================================================ +/// chcore::TSmartPath::IsNetworkPath +/// @date 2010/10/17 +/// +/// @brief Checks if the path is network one (\\server_name...) +/// @return True if it is, false otherwise. +// ============================================================================ +bool TSmartPath::IsNetworkPath() const { - return m_pPath && boost::starts_with(m_pPath->m_strPath, _T("\\\\?\\")); + if(!m_pPath) + return false; + + if(HasLengthExtension()) + return (m_pPath->m_strPath.length() > 6 && IsSeparator(m_pPath->m_strPath.at(4)) && IsSeparator(m_pPath->m_strPath.at(5))); // "\\?\\\server_name" + else + return (m_pPath->m_strPath.length() > 2 && IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1))); // "\\server_name" } +// ============================================================================ +/// chcore::TSmartPath::HasDrive +/// @date 2010/10/16 +/// +/// @brief Checks if path has a drive component. +/// @return True if it has, false otherwise. +// ============================================================================ bool TSmartPath::HasDrive() const { if(!m_pPath) @@ -496,6 +564,13 @@ return (m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')); } +// ============================================================================ +/// chcore::TSmartPath::GetDrive +/// @date 2010/10/16 +/// +/// @brief Retrieves drive from path. +/// @return Path with drive, empty if drive does not exist. +// ============================================================================ TSmartPath TSmartPath::GetDrive() const { if(!m_pPath) @@ -520,31 +595,182 @@ return TSmartPath(); } +// ============================================================================ +/// chcore::TSmartPath::HasServerName +/// @date 2010/10/17 +/// +/// @brief +/// @return +// ============================================================================ +bool TSmartPath::HasServerName() const +{ + if(!m_pPath) + return false; + + if(HasLengthExtension()) + return (m_pPath->m_strPath.length() > 6 && IsSeparator(m_pPath->m_strPath.at(4)) && IsSeparator(m_pPath->m_strPath.at(5)) && std::isalnum(m_pPath->m_strPath.at(6))); + else + return (m_pPath->m_strPath.length() > 2 && IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1)) && std::isalnum(m_pPath->m_strPath.at(2))); +} + +// ============================================================================ +/// chcore::TSmartPath::GetServerName +/// @date 2010/10/17 +/// +/// @brief Retrieves server name from path (if network path). +/// @return Path containing server name (with prepended \\) +// ============================================================================ +TSmartPath TSmartPath::GetServerName() const +{ + if(!m_pPath) + return TSmartPath(); + + std::wstring wstrPath; + if(HasLengthExtension()) + { + if(m_pPath->m_strPath.length() > 6 && IsSeparator(m_pPath->m_strPath.at(4)) && IsSeparator(m_pPath->m_strPath.at(5)) && std::isalnum(m_pPath->m_strPath.at(6))) + { + size_t stEndPos = m_pPath->m_strPath.find_first_of(_T("\\/"), 6); + if(stEndPos == std::wstring::npos) + wstrPath.insert(wstrPath.end(), m_pPath->m_strPath.begin() + 4, m_pPath->m_strPath.end()); + else + wstrPath.insert(wstrPath.end(), m_pPath->m_strPath.begin() + 4, m_pPath->m_strPath.begin() + stEndPos); + return PathFromString(wstrPath); + } + } + else + { + if(m_pPath->m_strPath.length() > 2 && IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1)) && std::isalnum(m_pPath->m_strPath.at(2))) + { + size_t stEndPos = m_pPath->m_strPath.find_first_of(_T("\\/"), 2); + if(stEndPos == std::wstring::npos) + wstrPath.insert(wstrPath.end(), m_pPath->m_strPath.begin(), m_pPath->m_strPath.end()); + else + wstrPath.insert(wstrPath.end(), m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + stEndPos); + return PathFromString(wstrPath); + } + } + + return TSmartPath(); +} + +// ============================================================================ +/// chcore::TSmartPath::HasFileRoot +/// @date 2010/10/17 +/// +/// @brief Checks if this path has a file root part. +/// @return True if it has, false otherwise. +// ============================================================================ +bool TSmartPath::HasFileRoot() const +{ + if(!m_pPath) + return false; + + if(HasLengthExtension()) + { + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + return (stIndex != std::wstring::npos && stIndex >= 4); + } + else + { + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + return (stIndex != std::wstring::npos); + } +} + +// ============================================================================ +/// chcore::TSmartPath::GetFileRoot +/// @date 2010/10/17 +/// +/// @brief Retrieves the root of the file. +/// @return File root as path, empty path if does not exist. +// ============================================================================ +TSmartPath TSmartPath::GetFileRoot() const +{ + if(!m_pPath) + return TSmartPath(); + + if(HasLengthExtension()) + { + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos && stIndex >= 4) + { + std::wstring wstrPath(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + stIndex + 1); + return PathFromString(wstrPath); + } + } + else + { + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos) + { + std::wstring wstrPath(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + stIndex + 1); + return PathFromString(wstrPath); + } + } + + return TSmartPath(); +} + +// ============================================================================ +/// chcore::TSmartPath::HasFileDir +/// @date 2010/10/16 +/// +/// @brief Checks if path contains directory specification. +/// @return True if it contains one, false otherwise. +// ============================================================================ bool TSmartPath::HasFileDir() const { if(!m_pPath) return false; size_t stStart = 0; if(HasLengthExtension()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 4); + { + if(IsNetworkPath()) + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 6); + else + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 4); + } else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); + { + if(IsNetworkPath()) + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); + else + stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); + } size_t stEnd = m_pPath->m_strPath.find_last_of(_T("/\\")); return (stStart != std::wstring::npos && stEnd >= stStart); } +// ============================================================================ +/// chcore::TSmartPath::GetFileDir +/// @date 2010/10/16 +/// +/// @brief Retrieves the directory specification from path. +/// @return Directory specification, empty path if not found. +// ============================================================================ TSmartPath TSmartPath::GetFileDir() const { if(!m_pPath) return TSmartPath(); size_t stStart = 0; if(HasLengthExtension()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 4); + { + if(IsNetworkPath()) + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 6); + else + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 4); + } else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); + { + if(IsNetworkPath()) + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); + else + stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); + } size_t stEnd = m_pPath->m_strPath.find_last_of(_T("/\\")); if(stStart != std::wstring::npos && stEnd >= stStart) @@ -556,6 +782,13 @@ return TSmartPath(); } +// ============================================================================ +/// chcore::TSmartPath::HasFileTitle +/// @date 2010/10/16 +/// +/// @brief Checks if the path has file title part. +/// @return True if it has one, false otherwise. +// ============================================================================ bool TSmartPath::HasFileTitle() const { if(!m_pPath) @@ -573,6 +806,13 @@ return stEnd > stStart + 1; } +// ============================================================================ +/// chcore::TSmartPath::GetFileTitle +/// @date 2010/10/16 +/// +/// @brief Retrieves file title from path. +/// @return File title. Empty if does not exist. +// ============================================================================ TSmartPath TSmartPath::GetFileTitle() const { if(!m_pPath) @@ -591,6 +831,13 @@ return PathFromString(wstrDir); } +// ============================================================================ +/// chcore::TSmartPath::HasExtension +/// @date 2010/10/16 +/// +/// @brief Checks if this path has a file extension. +/// @return True if it has, false otherwise. +// ============================================================================ bool TSmartPath::HasExtension() const { if(!m_pPath) @@ -601,6 +848,13 @@ return stIndex != std::wstring::npos && (m_pPath->m_strPath.at(stIndex) == _T('.')); } +// ============================================================================ +/// chcore::TSmartPath::GetExtension +/// @date 2010/10/16 +/// +/// @brief Retrieves file extension from this path. +/// @return Extension part or empty if does not exist. +// ============================================================================ TSmartPath TSmartPath::GetExtension() const { if(!m_pPath) @@ -614,6 +868,13 @@ return TSmartPath(); } +// ============================================================================ +/// chcore::TSmartPath::HasFileName +/// @date 2010/10/16 +/// +/// @brief Checks if this path contains filename part. +/// @return True if filename exists, false otherwise. +// ============================================================================ bool TSmartPath::HasFileName() const { if(!m_pPath) @@ -631,6 +892,13 @@ } } +// ============================================================================ +/// chcore::TSmartPath::GetFileName +/// @date 2010/10/16 +/// +/// @brief Retrieves filename part of this path. +/// @return Filename, or empty if does not exist. +// ============================================================================ TSmartPath TSmartPath::GetFileName() const { if(!m_pPath) @@ -640,40 +908,166 @@ { size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); if(stIndex != std::wstring::npos && stIndex >= 4) - return PathFromString(std::wstring(m_pPath->m_strPath.begin() + stIndex, m_pPath->m_strPath.end())); // ".txt" for "c:\windows\test.txt" + return PathFromString(std::wstring(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end())); // "test.txt" for "c:\windows\test.txt" } else { size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); if(stIndex != std::wstring::npos) - return PathFromString(std::wstring(m_pPath->m_strPath.begin() + stIndex, m_pPath->m_strPath.end())); // ".txt" for "c:\windows\test.txt" + return PathFromString(std::wstring(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end())); // "test.txt" for "c:\windows\test.txt" } return TSmartPath(); } // ============================================================================ -/// chcore::TSmartPath::DeleteLastComponent -/// @date 2010/10/12 +/// chcore::TSmartPath::DeleteFileName +/// @date 2010/10/17 /// -/// @brief Removes the last component of a path (i.e. test.txt for c:\test\test.txt) +/// @brief Deletes the filename part of this path if exists. // ============================================================================ -void TSmartPath::DeleteLastComponent() +void TSmartPath::DeleteFileName() { - if(m_pPath) - { - boost::iterator_range rangeIter = boost::find_last(m_pPath->m_strPath, DEFAULT_PATH_SEPARATOR); + if(!m_pPath) + return; - if(rangeIter.end() != m_pPath->m_strPath.end()) + if(HasLengthExtension()) + { + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos && stIndex >= 4) { - size_t stOffset = std::distance(m_pPath->m_strPath.begin(), rangeIter.end()); PrepareToWrite(); - m_pPath->m_strPath.erase(m_pPath->m_strPath.begin() + stOffset, m_pPath->m_strPath.end()); + m_pPath->m_strPath.erase(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end()); // "test.txt" for "c:\windows\test.txt" } } + else + { + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos) + { + PrepareToWrite(); + m_pPath->m_strPath.erase(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end()); // "test.txt" for "c:\windows\test.txt" + } + } } // ============================================================================ +/// chcore::TSmartPath::EndsWithSeparator +/// @date 2010/10/16 +/// +/// @brief Checks if path end with a path separator (/ or \) +/// @return True if path ends with separator, false otherwise. +// ============================================================================ +bool TSmartPath::EndsWithSeparator() const +{ + if(!m_pPath) + return false; + + size_t stThisSize = m_pPath->m_strPath.length(); + if(stThisSize > 0) + { + wchar_t wchLastChar = m_pPath->m_strPath.at(stThisSize - 1); + return (wchLastChar == _T('\\') || wchLastChar == _T('/')); + } + + return false; +} + +// ============================================================================ +/// chcore::TSmartPath::AppendSeparatorIfDoesNotExist +/// @date 2010/10/16 +/// +/// @brief Appends separator to this path if does not exist already. +// ============================================================================ +void TSmartPath::AppendSeparatorIfDoesNotExist() +{ + if(!EndsWithSeparator()) + { + PrepareToWrite(); + m_pPath->m_strPath += _T("\\"); + } +} + +// ============================================================================ +/// chcore::TSmartPath::StripSeparatorAtEnd +/// @date 2010/10/17 +/// +/// @brief Strips separator at the end of path if exists. +// ============================================================================ +void TSmartPath::StripSeparatorAtEnd() +{ + if(EndsWithSeparator()) + { + PrepareToWrite(); + m_pPath->m_strPath.erase(m_pPath->m_strPath.end() - 1); + } +} + +// ============================================================================ +/// chcore::TSmartPath::StartsWithSeparator +/// @date 2010/10/16 +/// +/// @brief Checks if path starts with a separator. +/// @return True if path starts with separator, false otherwise. +// ============================================================================ +bool TSmartPath::StartsWithSeparator() const +{ + if(!m_pPath) + return false; + + wchar_t wchLastChar = 0; + if(HasLengthExtension()) + { + if(m_pPath->m_strPath.length() > 4) + wchLastChar = m_pPath->m_strPath.at(4); + } + else + { + if(m_pPath->m_strPath.length() > 0) + wchLastChar = m_pPath->m_strPath.at(0); + } + + return (wchLastChar == _T('\\') || wchLastChar == _T('/')); +} + +// ============================================================================ +/// chcore::TSmartPath::PrependSeparatorIfDoesNotExist +/// @date 2010/10/17 +/// +/// @brief Prepends a separator to this path if not exist already. +// ============================================================================ +void TSmartPath::PrependSeparatorIfDoesNotExist() +{ + if(!StartsWithSeparator()) + { + PrepareToWrite(); + if(HasLengthExtension()) + m_pPath->m_strPath.insert(4, _T("\\")); + else + m_pPath->m_strPath.insert(0, _T("\\")); + } +} + +// ============================================================================ +/// chcore::TSmartPath::StripSeparatorAtFront +/// @date 2010/10/17 +/// +/// @brief Strips separator at the front of this path (if exists). +// ============================================================================ +void TSmartPath::StripSeparatorAtFront() +{ + if(StartsWithSeparator()) + { + PrepareToWrite(); + + if(HasLengthExtension()) + m_pPath->m_strPath.erase(4); + else + m_pPath->m_strPath.erase(0); + } +} + +// ============================================================================ /// TSmartPath::IsEmpty /// @date 2010/10/07 /// @@ -705,6 +1099,19 @@ } // ============================================================================ +/// chcore::TSmartPath::IsSeparator +/// @date 2010/10/17 +/// +/// @brief Checks if the character is a separator. +/// @param[in] wchSeparator - Character to be checked. +/// @return True if it is a separator, false otherwise. +// ============================================================================ +bool TSmartPath::IsSeparator(wchar_t wchSeparator) +{ + return (wchSeparator == _T('\\') || wchSeparator == _T('/')); +} + +// ============================================================================ /// chcore::PathFromString /// @date 2010/10/12 /// Index: src/libchcore/TPath.h =================================================================== diff -u -r280a99da8f4dfa84ea3587c5c9df3363ac0c8f4f -r591f291e22d2ece89acb266c8aa0b05c257a407c --- src/libchcore/TPath.h (.../TPath.h) (revision 280a99da8f4dfa84ea3587c5c9df3363ac0c8f4f) +++ src/libchcore/TPath.h (.../TPath.h) (revision 591f291e22d2ece89acb266c8aa0b05c257a407c) @@ -76,8 +76,8 @@ const wchar_t* ToString() const; std::wstring ToWString() const; - // other operations - void Clear() throw(); + // other operations + void Clear() throw(); bool Compare(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const; bool IsChildOf(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const; @@ -87,26 +87,42 @@ void AppendIfNotExists(const wchar_t* pszPostfix, bool bCaseSensitive = DefaultCaseSensitivity); void CutIfExists(const wchar_t* pszPostfix, bool bCaseSensitive = DefaultCaseSensitivity); - void DeleteLastComponent(); - TSmartPath GetLastComponent(); + bool HasLengthExtension() const; // checks if path is prefixed with "\\?\" + void AddLengthExtension(); + void DeleteLengthExtension(); - bool HasLengthExtension() const; + bool IsNetworkPath() const; bool HasDrive() const; - TSmartPath GetDrive() const; // c: for c:\windows\test.txt + TSmartPath GetDrive() const; // c: for c:\windows\test.txt - bool HasFileDir() const; // \windows\ for c:\windows\test.txt - TSmartPath GetFileDir() const; // \windows\ for c:\windows\test.txt + bool HasServerName() const; + TSmartPath GetServerName() const; - bool HasFileTitle() const; // test for c:\windows\test.txt - TSmartPath GetFileTitle() const; // test for c:\windows\test.txt + bool HasFileRoot() const; + TSmartPath GetFileRoot() const; // "c:\windows\" for "c:\windows\test.txt" - bool HasExtension() const; // txt for c:\windows\test.txt - TSmartPath GetExtension() const; // txt for c:\windows\test.txt + bool HasFileDir() const; // \windows\ for c:\windows\test.txt + TSmartPath GetFileDir() const; // \windows\ for c:\windows\test.txt - bool HasFileName() const; // test.txt for c:\windows\test.txt - TSmartPath GetFileName() const; // test.txt for c:\windows\test.txt + bool HasFileTitle() const; // test for c:\windows\test.txt + TSmartPath GetFileTitle() const; // test for c:\windows\test.txt + bool HasExtension() const; // txt for c:\windows\test.txt + TSmartPath GetExtension() const; // txt for c:\windows\test.txt + + bool HasFileName() const; // test.txt for c:\windows\test.txt + TSmartPath GetFileName() const; // test.txt for c:\windows\test.txt + void DeleteFileName(); // test.txt for c:\windows\test.txt + + bool EndsWithSeparator() const; + void AppendSeparatorIfDoesNotExist(); + void StripSeparatorAtEnd(); + + bool StartsWithSeparator() const; + void PrependSeparatorIfDoesNotExist(); + void StripSeparatorAtFront(); + bool IsEmpty() const; // Serialization @@ -128,6 +144,8 @@ protected: void PrepareToWrite(); + static bool IsSeparator(wchar_t wchSeparator); + protected: TPath* m_pPath; };