Index: src/ch/TLocalFilesystem.cpp =================================================================== diff -u -ra3800c2f65fa66354e072b34c9e9970af49236b6 -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e --- src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision a3800c2f65fa66354e072b34c9e9970af49236b6) +++ src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) @@ -26,44 +26,52 @@ #include "FileInfo.h" #include "..\Common\FileSupport.h" #include "DataBuffer.h" +#include void TLocalFilesystem::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType) { - TCHAR drv[_MAX_DRIVE + 1]; + chcore::TSmartPath pathDrive = spPath.GetDrive(); - _tsplitpath(spPath.ToString(), drv, NULL, NULL, NULL); - if(lstrlen(drv) != 0) + if(!spPath.IsNetworkPath()) { - // add '\\' - lstrcat(drv, _T("\\")); - _tcsupr(drv); + std::wstring wstrDrive = spPath.ToWString(); - // disk number - if(piDrvNum) - *piDrvNum=drv[0]-_T('A'); + if(wstrDrive.empty()) + { + if(piDrvNum) + *piDrvNum = -1; - // disk type - if(puiDrvType) + if(puiDrvType) + *puiDrvType = DRIVE_UNKNOWN; + } + else { - *puiDrvType=GetDriveType(drv); - if(*puiDrvType == DRIVE_NO_ROOT_DIR) - *puiDrvType=DRIVE_UNKNOWN; + // disk number + if(piDrvNum) + { + boost::to_upper(wstrDrive); + *piDrvNum = wstrDrive.at(0) - _T('A'); + } + + // disk type + if(puiDrvType) + { + pathDrive.AppendSeparatorIfDoesNotExist(); + + *puiDrvType = GetDriveType(pathDrive.ToString()); + if(*puiDrvType == DRIVE_NO_ROOT_DIR) + *puiDrvType = DRIVE_UNKNOWN; + } } } else { - // there's no disk in a path + // network path if(piDrvNum) - *piDrvNum=-1; + *piDrvNum = -1; if(puiDrvType) - { - // check for unc path - if(_tcsncmp(spPath.ToString(), _T("\\\\"), 2) == 0) - *puiDrvType=DRIVE_REMOTE; - else - *puiDrvType=DRIVE_UNKNOWN; - } + *puiDrvType = DRIVE_REMOTE; } } @@ -112,9 +120,31 @@ return ::SetFileAttributes(PrependPathExtensionIfNeeded(pathFileDir).ToString(), dwAttributes) != FALSE; } -bool TLocalFilesystem::CreateDirectory(const chcore::TSmartPath& pathDirectory) +bool TLocalFilesystem::CreateDirectory(const chcore::TSmartPath& pathDirectory, bool bCreateFullPath) { - return ::CreateDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString(), NULL) != FALSE; + if(!bCreateFullPath) + return ::CreateDirectory(PrependPathExtensionIfNeeded(pathDirectory).ToString(), NULL) != FALSE; + else + { + std::vector vComponents; + pathDirectory.SplitPath(vComponents); + + chcore::TSmartPath pathToTest; + BOOST_FOREACH(const chcore::TSmartPath& pathComponent, vComponents) + { + pathToTest += pathComponent; + // try to create subsequent paths + if(!pathToTest.IsDrive() && !pathToTest.IsServerName()) + { + // try to create the specified path + BOOL bRes = ::CreateDirectory(PrependPathExtensionIfNeeded(pathToTest).ToString(), NULL); + if(!bRes && GetLastError() != ERROR_ALREADY_EXISTS) + return false; + } + } + } + + return true; } bool TLocalFilesystem::RemoveDirectory(const chcore::TSmartPath& pathFile) Index: src/ch/TLocalFilesystem.h =================================================================== diff -u -ra3800c2f65fa66354e072b34c9e9970af49236b6 -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e --- src/ch/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision a3800c2f65fa66354e072b34c9e9970af49236b6) +++ src/ch/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) @@ -42,7 +42,7 @@ static bool SetFileDirectoryTime(const chcore::TSmartPath& pathFileDir, const FILETIME& ftCreationTime, const FILETIME& ftLastAccessTime, const FILETIME& ftLastWriteTime); static bool SetAttributes(const chcore::TSmartPath& pathFileDir, DWORD dwAttributes); - static bool CreateDirectory(const chcore::TSmartPath& pathDirectory); + static bool CreateDirectory(const chcore::TSmartPath& pathDirectory, bool bCreateFullPath); static bool RemoveDirectory(const chcore::TSmartPath& pathFile); static bool DeleteFile(const chcore::TSmartPath& pathFile); Index: src/ch/TSubTaskBase.cpp =================================================================== diff -u -ra3800c2f65fa66354e072b34c9e9970af49236b6 -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e --- src/ch/TSubTaskBase.cpp (.../TSubTaskBase.cpp) (revision a3800c2f65fa66354e072b34c9e9970af49236b6) +++ src/ch/TSubTaskBase.cpp (.../TSubTaskBase.cpp) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) @@ -80,7 +80,7 @@ chcore::TSmartPath pathCombined = pathDst + spFileInfo->GetFullFilePath().GetFileDir(); // force create directory - SHCreateDirectoryEx(NULL, pathCombined.ToString(), NULL); + TLocalFilesystem::CreateDirectory(pathCombined, true); return pathCombined + spFileInfo->GetFullFilePath().GetFileName(); } Index: src/ch/TSubTaskCopyMove.cpp =================================================================== diff -u -r7749d67cd70821fef9cc51303d42625fbcc2aa9d -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e --- src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 7749d67cd70821fef9cc51303d42625fbcc2aa9d) +++ src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) @@ -178,7 +178,7 @@ if(spFileInfo->IsDirectory()) { bool bRetry = true; - if(bRetry && !TLocalFilesystem::CreateDirectory(ccp.pathDstFile) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS ) + if(bRetry && !TLocalFilesystem::CreateDirectory(ccp.pathDstFile, false) && (dwLastError=GetLastError()) != ERROR_ALREADY_EXISTS ) { // log fmt.SetFormat(_T("Error %errno while calling CreateDirectory %path (ProcessFiles)")); Index: src/libchcore/TPath.cpp =================================================================== diff -u -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e --- src/libchcore/TPath.cpp (.../TPath.cpp) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/libchcore/TPath.cpp (.../TPath.cpp) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) @@ -18,8 +18,12 @@ ***************************************************************************/ #include "stdafx.h" #include +#include #include "TPath.h" +#pragma warning(push) +#pragma warning(disable: 4996) #include +#pragma warning(pop) #include "../libicpf/exception.h" #include @@ -34,8 +38,8 @@ /// @brief Constructs the TPath object. // ============================================================================ TPath::TPath() : - m_strPath(), - m_lRefCount(1) +m_strPath(), +m_lRefCount(1) { } @@ -46,8 +50,8 @@ /// @brief Constructs the TPath object. // ============================================================================ TPath::TPath(const TPath& rSrc) : - m_strPath(rSrc.m_strPath), - m_lRefCount(1) +m_strPath(rSrc.m_strPath), +m_lRefCount(1) { } @@ -121,7 +125,7 @@ /// @brief Constructs an empty path. // ============================================================================ TSmartPath::TSmartPath() : - m_pPath(NULL) +m_pPath(NULL) { } @@ -133,7 +137,7 @@ /// @param[in] spPath - reference to another path object. // ============================================================================ TSmartPath::TSmartPath(const TSmartPath& spPath) : - m_pPath(spPath.m_pPath) +m_pPath(spPath.m_pPath) { if(m_pPath) m_pPath->AddRef(); @@ -250,27 +254,40 @@ // ============================================================================ TSmartPath TSmartPath::operator+(const TSmartPath& rPath) const { - TSmartPath spNewPath(*this); if(rPath.m_pPath && rPath.m_pPath->m_strPath.length() > 0) { - spNewPath.PrepareToWrite(); - - // 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; + // if this path is empty, then return the input one + if(!m_pPath || rPath.m_pPath->m_strPath.length() == 0) + return rPath; else { - spNewPath.m_pPath->m_strPath.erase(m_pPath->m_strPath.length() - 1); - spNewPath.m_pPath->m_strPath += rPath.m_pPath->m_strPath; + TSmartPath spNewPath(*this); + + // both paths contains something to be concatenated + spNewPath.PrepareToWrite(); + + // 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; } } - - return spNewPath; + else + { + // input path is empty, so return this path, whatever this is + return *this; + } } // ============================================================================ @@ -286,20 +303,27 @@ // if there is no path inside rPath, then there is no point in doing anything if(rPath.m_pPath && rPath.m_pPath->m_strPath.length() > 0) { - PrepareToWrite(); - - // 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; + // if this path is empty, then optimize by just assigning the input path to this one + if(!m_pPath || m_pPath->m_strPath.length() == 0) + *this = rPath; else { - m_pPath->m_strPath.erase(m_pPath->m_strPath.length() - 1); - m_pPath->m_strPath += rPath.m_pPath->m_strPath; + // both paths are not empty - do regular concatenation + PrepareToWrite(); + + // 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; + } } } @@ -388,6 +412,45 @@ } // ============================================================================ +/// TSmartPath::SplitPath +/// @date 2011/04/05 +/// +/// @brief Splits path to components. +/// @param[in] vComponents - receives the split path. +// ============================================================================ +void TSmartPath::SplitPath(std::vector& vComponents) const +{ + vComponents.clear(); + + if(IsNetworkPath()) + { + // server name first + vComponents.push_back(GetServerName()); + + // now the split directories + std::vector vDirSplit; + TSmartPath spDir = GetFileDir(); + spDir.SplitPath(vDirSplit); + + vComponents.insert(vComponents.end(), vDirSplit.begin(), vDirSplit.end()); + + // and file name last + vComponents.push_back(GetFileName()); + } + else + { + std::vector vStrings; + boost::split(vStrings, m_pPath->m_strPath, boost::is_any_of(_T("\\/"))); + + BOOST_FOREACH(const std::wstring& pathComponent, vStrings) + { + if(!pathComponent.empty()) + vComponents.push_back(PathFromWString(pathComponent)); + } + } +} + +// ============================================================================ /// TSmartPath::IsChildOf /// @date 2009/11/29 /// @@ -488,63 +551,33 @@ } // ============================================================================ -/// chcore::TSmartPath::HasLengthExtension -/// @date 2010/10/16 +/// chcore::TSmartPath::IsNetworkPath +/// @date 2010/10/17 /// -/// @brief Checks if the path has prefix allowing handling of longer paths (\\?\) -/// @return True if prefix exists, false otherwise. +/// @brief Checks if the path is network one (\\server_name...) +/// @return True if it is, false otherwise. // ============================================================================ -bool TSmartPath::HasLengthExtension() const +bool TSmartPath::IsNetworkPath() const { - return m_pPath && boost::starts_with(m_pPath->m_strPath, _T("\\\\?\\")); -} + if(!m_pPath) + return false; -// ============================================================================ -/// 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("\\\\?\\")); - } + 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::DeleteLengthExtension -/// @date 2010/10/16 +/// chcore::TSmartPath::IsDrive +/// @date 2011/04/05 /// -/// @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); - } -} - -// ============================================================================ -/// chcore::TSmartPath::IsNetworkPath -/// @date 2010/10/17 -/// -/// @brief Checks if the path is network one (\\server_name...) +/// @brief Checks if this path contains only drive specification (i.e. c:) /// @return True if it is, false otherwise. // ============================================================================ -bool TSmartPath::IsNetworkPath() const +bool TSmartPath::IsDrive() 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))); // "\\?\\\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" + return (m_pPath->m_strPath.length() == 2 && m_pPath->m_strPath.at(1) == _T(':')); } // ============================================================================ @@ -558,10 +591,8 @@ { if(!m_pPath) return false; - if(HasLengthExtension()) - return (m_pPath->m_strPath.length() >= 6 && m_pPath->m_strPath.at(5) == _T(':')); - else - return (m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')); + + return (m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')); } // ============================================================================ @@ -576,26 +607,36 @@ if(!m_pPath) return TSmartPath(); - if(HasLengthExtension()) + if(m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')) { - if(m_pPath->m_strPath.length() >= 6 && m_pPath->m_strPath.at(5) == _T(':')) - return PathFromString(std::wstring(m_pPath->m_strPath.begin() + 4, m_pPath->m_strPath.begin() + 6)); // c: for c:\windows\test.cpp + if(m_pPath->m_strPath.length() == 2) + return *this; + else + return PathFromWString(std::wstring(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + 2)); // c: for c:\windows\test.cpp } - else - { - if(m_pPath->m_strPath.length() >= 2 && m_pPath->m_strPath.at(1) == _T(':')) - { - if(m_pPath->m_strPath.length() == 2) - return *this; - else - return PathFromString(std::wstring(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + 2)); // c: for c:\windows\test.cpp - } - } return TSmartPath(); } // ============================================================================ +/// chcore::TSmartPath::IsServerName +/// @date 2011/04/05 +/// +/// @brief Checks if this path contains only the server specification (i.e. \\server - witn no ending backslash) +/// @return True is this path contains only server specification. +// ============================================================================ +bool TSmartPath::IsServerName() const +{ + if(!m_pPath) + return false; + + return (m_pPath->m_strPath.length() > 2 && // must have at least 3 characters... + IsSeparator(m_pPath->m_strPath.at(0)) && IsSeparator(m_pPath->m_strPath.at(1)) && // ... the first two of which are separators... + std::isalnum(m_pPath->m_strPath.at(2)) && // ... followed by at least one alphanumeric character... + m_pPath->m_strPath.find_first_of(_T("\\/"), 3) == std::wstring::npos); // ... with no additional separators (so \\abc is true, \\abc\ is not). +} + +// ============================================================================ /// chcore::TSmartPath::HasServerName /// @date 2010/10/17 /// @@ -607,10 +648,7 @@ 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))); + 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))); } // ============================================================================ @@ -626,30 +664,15 @@ return TSmartPath(); std::wstring wstrPath; - if(HasLengthExtension()) + 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))) { - 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); - } + 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 PathFromWString(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(); } @@ -666,16 +689,8 @@ 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); - } + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + return (stIndex != std::wstring::npos); } // ============================================================================ @@ -690,24 +705,12 @@ if(!m_pPath) return TSmartPath(); - if(HasLengthExtension()) + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos) { - 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); - } + std::wstring wstrPath(m_pPath->m_strPath.begin(), m_pPath->m_strPath.begin() + stIndex + 1); + return PathFromWString(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(); } @@ -725,20 +728,10 @@ return false; size_t stStart = 0; - if(HasLengthExtension()) - { - if(IsNetworkPath()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 6); - else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 4); - } + if(IsNetworkPath()) + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); else - { - if(IsNetworkPath()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); - else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); - } + 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); @@ -757,26 +750,16 @@ return TSmartPath(); size_t stStart = 0; - if(HasLengthExtension()) - { - if(IsNetworkPath()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 6); - else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 4); - } + if(IsNetworkPath()) + stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); else - { - if(IsNetworkPath()) - stStart = m_pPath->m_strPath.find_first_of(_T("/\\"), 2); - else - stStart = m_pPath->m_strPath.find_first_of(_T("/\\")); - } + 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) { std::wstring wstrDir(m_pPath->m_strPath.begin() + stStart, m_pPath->m_strPath.begin() + stEnd + 1); - return PathFromString(wstrDir); + return PathFromWString(wstrDir); } return TSmartPath(); @@ -828,7 +811,7 @@ stEnd = m_pPath->m_strPath.length(); std::wstring wstrDir(m_pPath->m_strPath.begin() + stStart + 1, m_pPath->m_strPath.begin() + stEnd); - return PathFromString(wstrDir); + return PathFromWString(wstrDir); } // ============================================================================ @@ -863,7 +846,7 @@ size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/.")); if(stIndex != std::wstring::npos && m_pPath->m_strPath.at(stIndex) == _T('.')) - return PathFromString(std::wstring(m_pPath->m_strPath.begin() + stIndex, m_pPath->m_strPath.end())); // ".txt" for "c:\windows\test.txt" + return PathFromWString(std::wstring(m_pPath->m_strPath.begin() + stIndex, m_pPath->m_strPath.end())); // ".txt" for "c:\windows\test.txt" return TSmartPath(); } @@ -880,16 +863,8 @@ 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 && stIndex != m_pPath->m_strPath.length() - 1); - } - else - { - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - return (stIndex != std::wstring::npos && stIndex != m_pPath->m_strPath.length() - 1); - } + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + return (stIndex != std::wstring::npos && stIndex != m_pPath->m_strPath.length() - 1); } // ============================================================================ @@ -904,18 +879,9 @@ 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) - 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 + 1, m_pPath->m_strPath.end())); // "test.txt" for "c:\windows\test.txt" - } + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos) + return PathFromWString(std::wstring(m_pPath->m_strPath.begin() + stIndex + 1, m_pPath->m_strPath.end())); // "test.txt" for "c:\windows\test.txt" return TSmartPath(); } @@ -931,24 +897,12 @@ if(!m_pPath) return; - if(HasLengthExtension()) + size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); + if(stIndex != std::wstring::npos) { - size_t stIndex = m_pPath->m_strPath.find_last_of(_T("\\/")); - if(stIndex != std::wstring::npos && stIndex >= 4) - { - 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" - } + 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" } - 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" - } - } } // ============================================================================ @@ -1016,16 +970,8 @@ 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); - } + if(m_pPath->m_strPath.length() > 0) + wchLastChar = m_pPath->m_strPath.at(0); return (wchLastChar == _T('\\') || wchLastChar == _T('/')); } @@ -1041,10 +987,7 @@ if(!StartsWithSeparator()) { PrepareToWrite(); - if(HasLengthExtension()) - m_pPath->m_strPath.insert(4, _T("\\")); - else - m_pPath->m_strPath.insert(0, _T("\\")); + m_pPath->m_strPath.insert(0, _T("\\")); } } @@ -1060,10 +1003,7 @@ { PrepareToWrite(); - if(HasLengthExtension()) - m_pPath->m_strPath.erase(4); - else - m_pPath->m_strPath.erase(0); + m_pPath->m_strPath.erase(0); } } @@ -1078,18 +1018,42 @@ return !m_pPath || m_pPath->m_strPath.empty(); } +// ============================================================================ +/// chcore::TSmartPath::GetLength +/// @date 2011/04/05 +/// +/// @brief Retrieves path length in characters. +/// @return Path length. +// ============================================================================ size_t TSmartPath::GetLength() const { if(!m_pPath) return 0; return m_pPath->m_strPath.length(); } +// ============================================================================ +/// chcore::TSmartPath::StoreInConfig +/// @date 2011/04/05 +/// +/// @brief Stores the path in configuration file. +/// @param[in] rConfig - configuration object to store information in. +/// @param[in] pszPropName - property name under which to store the path. +// ============================================================================ void TSmartPath::StoreInConfig(chcore::TConfig& rConfig, PCTSTR pszPropName) const { rConfig.SetValue(pszPropName, m_pPath ? m_pPath->m_strPath : std::wstring()); } +// ============================================================================ +/// chcore::TSmartPath::ReadFromConfig +/// @date 2011/04/05 +/// +/// @brief Reads a path from configuration file. +/// @param[in] rConfig - configuration object to read path from. +/// @param[in] pszPropName - property name from under which to read the path. +/// @return True if path properly read, false otherwise. +// ============================================================================ bool TSmartPath::ReadFromConfig(const chcore::TConfig& rConfig, PCTSTR pszPropName) { std::wstring wstrPath; @@ -1155,14 +1119,14 @@ } // ============================================================================ -/// chcore::PathFromString +/// chcore::PathFromWString /// @date 2010/10/12 /// /// @brief Creates a path object from string. /// @param[in] pszPath - string containing path. /// @return New path object. // ============================================================================ -TSmartPath PathFromString(const std::wstring& strPath) +TSmartPath PathFromWString(const std::wstring& strPath) { TSmartPath spPath; spPath.FromString(strPath); @@ -1176,7 +1140,7 @@ /// @brief Constructs an empty path container object. // ============================================================================ TPathContainer::TPathContainer() : - m_vPaths() +m_vPaths() { } @@ -1188,7 +1152,7 @@ /// @param[in] rSrcContainer - path container to copy paths from. // ============================================================================ TPathContainer::TPathContainer(const TPathContainer& rSrcContainer) : - m_vPaths(rSrcContainer.m_vPaths) +m_vPaths(rSrcContainer.m_vPaths) { } @@ -1274,7 +1238,7 @@ { if(stIndex > m_vPaths.size()) THROW_CORE_EXCEPTION(eBoundsExceeded); - + m_vPaths[stIndex] = spPath; } @@ -1350,7 +1314,7 @@ { BOOST_FOREACH(const std::wstring& wstrPath, vPaths) { - m_vPaths.push_back(PathFromString(wstrPath)); + m_vPaths.push_back(PathFromWString(wstrPath)); } return true; } Index: src/libchcore/TPath.h =================================================================== diff -u -re30c2b40bd1b533d8740edc88d80b2fb340f3466 -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e --- src/libchcore/TPath.h (.../TPath.h) (revision e30c2b40bd1b533d8740edc88d80b2fb340f3466) +++ src/libchcore/TPath.h (.../TPath.h) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) @@ -80,6 +80,8 @@ // other operations void Clear() throw(); + void SplitPath(std::vector& vComponents) const; + bool Compare(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const; bool IsChildOf(const TSmartPath& rPath, bool bCaseSensitive = DefaultCaseSensitivity) const; @@ -88,15 +90,13 @@ void AppendIfNotExists(const wchar_t* pszPostfix, bool bCaseSensitive = DefaultCaseSensitivity); void CutIfExists(const wchar_t* pszPostfix, bool bCaseSensitive = DefaultCaseSensitivity); - bool HasLengthExtension() const; // checks if path is prefixed with "\\?\" - void AddLengthExtension(); - void DeleteLengthExtension(); - bool IsNetworkPath() const; + bool IsDrive() const; bool HasDrive() const; TSmartPath GetDrive() const; // c: for c:\windows\test.txt + bool IsServerName() const; bool HasServerName() const; TSmartPath GetServerName() const; @@ -162,7 +162,7 @@ }; LIBCHCORE_API TSmartPath PathFromString(const wchar_t* pszPath); -LIBCHCORE_API TSmartPath PathFromString(const std::wstring& strPath); +LIBCHCORE_API TSmartPath PathFromWString(const std::wstring& strPath); class LIBCHCORE_API TPathContainer {