Index: src/libchcore/TPath.cpp
===================================================================
diff -u -N -r9545b48aadb1592a5bf22ac5a227b1666d7710c6 -rf18d23588f370de68d37adb285dcf5e046a8d37c
--- src/libchcore/TPath.cpp	(.../TPath.cpp)	(revision 9545b48aadb1592a5bf22ac5a227b1666d7710c6)
+++ src/libchcore/TPath.cpp	(.../TPath.cpp)	(revision f18d23588f370de68d37adb285dcf5e046a8d37c)
@@ -35,91 +35,94 @@
 
 #define DEFAULT_PATH_SEPARATOR _T("\\")
 
-// ============================================================================
-/// TPath::TPath
-/// @date 2009/11/29
-///
-/// @brief     Constructs the TPath object.
-// ============================================================================
-TPath::TPath() :
-m_strPath(),
-m_lRefCount(1)
+namespace details
 {
-}
+	// ============================================================================
+	/// TPath::TPath
+	/// @date 2009/11/29
+	///
+	/// @brief     Constructs the TPath object.
+	// ============================================================================
+	TPath::TPath() :
+		m_strPath(),
+		m_lRefCount(1)
+	{
+	}
 
-// ============================================================================
-/// TPath::TPath
-/// @date 2009/11/29
-///
-/// @brief     Constructs the TPath object.
-// ============================================================================
-TPath::TPath(const TPath& rSrc) :
-m_strPath(rSrc.m_strPath),
-m_lRefCount(1)
-{
-}
+	// ============================================================================
+	/// TPath::TPath
+	/// @date 2009/11/29
+	///
+	/// @brief     Constructs the TPath object.
+	// ============================================================================
+	TPath::TPath(const TPath& rSrc) :
+	m_strPath(rSrc.m_strPath),
+	m_lRefCount(1)
+	{
+	}
 
-// ============================================================================
-/// TPath::~TPath
-/// @date 2009/11/29
-///
-/// @brief     Destructs the TPath object.
-// ============================================================================
-TPath::~TPath()
-{
-}
+	// ============================================================================
+	/// TPath::~TPath
+	/// @date 2009/11/29
+	///
+	/// @brief     Destructs the TPath object.
+	// ============================================================================
+	TPath::~TPath()
+	{
+	}
 
-// ============================================================================
-/// TPath::Release
-/// @date 2009/11/29
-///
-/// @brief     Releases a reference to this object. Deletes the object if no reference exists.
-/// @return    Current reference count.
-// ============================================================================
-long TPath::Release()
-{
-	if(--m_lRefCount == 0)
+	// ============================================================================
+	/// TPath::Release
+	/// @date 2009/11/29
+	///
+	/// @brief     Releases a reference to this object. Deletes the object if no reference exists.
+	/// @return    Current reference count.
+	// ============================================================================
+	long TPath::Release()
 	{
-		delete this;
-		return 0;
+		if(--m_lRefCount == 0)
+		{
+			delete this;
+			return 0;
+		}
+		return m_lRefCount;
 	}
-	return m_lRefCount;
-}
 
-// ============================================================================
-/// TPath::New
-/// @date 2009/11/29
-///
-/// @brief     Allocates a new, empty TPath object.
-/// @return    Pointer to the newly allocated object.
-// ============================================================================
-TPath* TPath::New()
-{
-	return new TPath();
-}
+	// ============================================================================
+	/// TPath::New
+	/// @date 2009/11/29
+	///
+	/// @brief     Allocates a new, empty TPath object.
+	/// @return    Pointer to the newly allocated object.
+	// ============================================================================
+	TPath* TPath::New()
+	{
+		return new TPath();
+	}
 
-// ============================================================================
-/// TPath::New
-/// @date 2010/10/07
-///
-/// @brief     Clones this object.
-/// @return    Pointer to the newly allocated object.
-// ============================================================================
-TPath* TPath::Clone()
-{
-	return new TPath(*this);
-}
+	// ============================================================================
+	/// TPath::New
+	/// @date 2010/10/07
+	///
+	/// @brief     Clones this object.
+	/// @return    Pointer to the newly allocated object.
+	// ============================================================================
+	TPath* TPath::Clone()
+	{
+		return new TPath(*this);
+	}
 
-// ============================================================================
-/// TPath::Delete
-/// @date 2009/11/29
-///
-/// @brief     Deletes the TPath object 
-/// @param[in] pPath - pointer to the object to delete.
-// ============================================================================
-void TPath::Delete(TPath* pPath)
-{
-	delete pPath;
+	// ============================================================================
+	/// TPath::Delete
+	/// @date 2009/11/29
+	///
+	/// @brief     Deletes the TPath object 
+	/// @param[in] pPath - pointer to the object to delete.
+	// ============================================================================
+	void TPath::Delete(TPath* pPath)
+	{
+		delete pPath;
+	}
 }
 
 // ============================================================================
@@ -250,20 +253,7 @@
 // ============================================================================
 bool TSmartPath::operator==(const TSmartPath& rPath) const
 {
-	if(m_pPath == rPath.m_pPath)
-		return true;
-	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return false;
-	else
-	{
-		// NOTE: Windows paths are usually case insensitive and that would warrant usage of
-		//       iequals, however, in very specific cases (i.e. enabling case sensitivity for ntfs,
-		//       network paths) we need case sensitivity.
-		//       For now we'll try to support case sensitivity. If that will ever be a problem
-		//       we'll need to support case insensitivity (not trivial though).
-//		return boost::iequals(m_pPath->m_strPath, rPath.m_pPath->m_strPath);
-		return m_pPath->m_strPath == rPath.m_pPath->m_strPath;
-	}
+	return Compare(rPath) == 0;
 }
 
 // ============================================================================
@@ -276,12 +266,7 @@
 // ============================================================================
 bool TSmartPath::operator<(const TSmartPath& rPath) const
 {
-	if(m_pPath == rPath.m_pPath)
-		return false;
-	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return m_pPath < rPath.m_pPath;
-	else
-		return m_pPath->m_strPath < rPath.m_pPath->m_strPath;
+	return Compare(rPath) < 0;
 }
 
 // ============================================================================
@@ -294,12 +279,7 @@
 // ============================================================================
 bool TSmartPath::operator>(const TSmartPath& rPath) const
 {
-	if(m_pPath == rPath.m_pPath)
-		return false;
-	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return m_pPath > rPath.m_pPath;
-	else
-		return m_pPath->m_strPath > rPath.m_pPath->m_strPath;
+	return Compare(rPath) > 0;
 }
 
 // ============================================================================
@@ -338,7 +318,7 @@
 void TSmartPath::FromString(const wchar_t* pszPath)
 {
 	if(!pszPath)
-		THROW(_T("Invalid pointer"), 0, 0, 0);
+		THROW_CORE_EXCEPTION(eErr_InvalidArgument);
 
 	PrepareToWrite();
 	m_pPath->m_strPath = pszPath;
@@ -394,18 +374,26 @@
 /// @param[in] rPath - path to compare to.
 /// @return    Result of the comparison.
 // ============================================================================
-bool TSmartPath::Compare(const TSmartPath& rPath, bool bCaseSensitive) const
+int TSmartPath::Compare(const TSmartPath& rPath, bool bCaseSensitive) const
 {
 	if(m_pPath == rPath.m_pPath)
-		return true;
+		return 0;
 	else if(m_pPath == NULL || rPath.m_pPath == NULL)
-		return m_pPath == rPath.m_pPath;
+	{
+		TString strThis = m_pPath ? m_pPath->m_strPath : _T("");
+		TString strOther = rPath.m_pPath ? rPath.m_pPath->m_strPath : _T("");
+
+		if(bCaseSensitive)
+			return strThis.Compare(strOther);
+		else
+			return strThis.CompareNoCase(strOther);
+	}
 	else
 	{
 		if(bCaseSensitive)
-			return m_pPath->m_strPath.Compare(rPath.m_pPath->m_strPath) == 0;
+			return m_pPath->m_strPath.Compare(rPath.m_pPath->m_strPath);
 		else
-			return m_pPath->m_strPath.CompareNoCase(rPath.m_pPath->m_strPath) == 0;
+			return m_pPath->m_strPath.CompareNoCase(rPath.m_pPath->m_strPath);
 	}
 }
 
@@ -416,24 +404,24 @@
 /// @brief     Splits path to components.
 /// @param[in] vComponents - receives the split path.
 // ============================================================================
-void TSmartPath::SplitPath(std::vector<TSmartPath>& vComponents) const
+void TSmartPath::SplitPath(TPathContainer& vComponents) const
 {
-	vComponents.clear();
+	vComponents.Clear();
 
 	if(IsNetworkPath())
 	{
 		// server name first
-		vComponents.push_back(GetServerName());
+		vComponents.Add(GetServerName());
 
 		// now the split directories
-		std::vector<TSmartPath> vDirSplit;
+		TPathContainer vDirSplit;
 		TSmartPath spDir = GetFileDir();
 		spDir.SplitPath(vDirSplit);
 
-		vComponents.insert(vComponents.end(), vDirSplit.begin(), vDirSplit.end());
+		vComponents.Append(vDirSplit);
 
 		// and file name last
-		vComponents.push_back(GetFileName());
+		vComponents.Add(GetFileName());
 	}
 	else
 	{
@@ -444,7 +432,7 @@
 		{
 			const TString& strComponent = vStrings.GetAt(stIndex);
 			if(!strComponent.IsEmpty())
-				vComponents.push_back(PathFromWString(strComponent));
+				vComponents.Add(PathFromWString(strComponent));
 		}
 	}
 }
@@ -477,10 +465,10 @@
 /// @param[in] bCaseSensitive - Compare path with case sensitivity on/off.
 /// @return    True if conversion to relative path succeeded, false otherwise.
 // ============================================================================
-void TSmartPath::MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive)
+bool TSmartPath::MakeRelativePath(const TSmartPath& rReferenceBasePath, bool bCaseSensitive)
 {
 	if(!m_pPath || !rReferenceBasePath.m_pPath)
-		return;		// nothing to do; in this case we might as well treat the path as relative one
+		return true;		// nothing to do; in this case we might as well treat the path as relative one
 
 	bool bStartsWith = false;
 	if(bCaseSensitive)
@@ -492,9 +480,10 @@
 	{
 		PrepareToWrite();
 		m_pPath->m_strPath.Delete(0, rReferenceBasePath.m_pPath->m_strPath.GetLength());
+		return true;
 	}
 	else
-		THROW(_T("Incompatible paths"), 0, 0, 0);
+		return false;
 }
 
 // ============================================================================
@@ -692,7 +681,7 @@
 		if(stEndPos == TString::npos)
 			wstrPath = m_pPath->m_strPath;
 		else
-			wstrPath = m_pPath->m_strPath.Left(stEndPos - 1);
+			wstrPath = m_pPath->m_strPath.Left(stEndPos);
 		return PathFromWString(wstrPath);
 	}
 
@@ -771,8 +760,10 @@
 	size_t stStart = 0;
 	if(IsNetworkPath())
 		stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"), 2);
-	else
+	else if(HasDrive())
 		stStart = m_pPath->m_strPath.FindFirstOf(_T("/\\"));
+	else
+		stStart = 0;
 
 	size_t stEnd = m_pPath->m_strPath.FindLastOf(_T("/\\"));
 	if(stStart != TString::npos && stEnd >= stStart)
@@ -823,10 +814,12 @@
 		return *this;
 	if(stStart == TString::npos)	// if does not exist, start from beginning
 		stStart = 0;
+	else
+		++stStart;
 	if(stEnd == TString::npos || stEnd < stStart)		// if does not exist or we have ".\\", use up to the end
 		stEnd = m_pPath->m_strPath.GetLength();
 
-	return PathFromWString(m_pPath->m_strPath.MidRange(stStart + 1, stEnd));
+	return PathFromWString(m_pPath->m_strPath.MidRange(stStart, stEnd));
 }
 
 // ============================================================================
@@ -879,7 +872,10 @@
 		return false;
 
 	size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/"));
-	return (stIndex != TString::npos && stIndex != m_pPath->m_strPath.GetLength() - 1);
+	if(stIndex == TString::npos)	// no path separator?
+		return true;
+	else
+		return (stIndex != TString::npos && stIndex != m_pPath->m_strPath.GetLength() - 1);
 }
 
 // ============================================================================
@@ -897,8 +893,8 @@
 	size_t stIndex = m_pPath->m_strPath.FindLastOf(_T("\\/"));
 	if(stIndex != TString::npos)
 		return PathFromWString(m_pPath->m_strPath.MidRange(stIndex + 1, m_pPath->m_strPath.GetLength()));	// "test.txt" for "c:\windows\test.txt"
-
-	return TSmartPath();
+	else
+		return *this;
 }
 
 // ============================================================================
@@ -918,6 +914,11 @@
 		PrepareToWrite();
 		m_pPath->m_strPath.Delete(stIndex + 1, m_pPath->m_strPath.GetLength() - stIndex - 1);	// "test.txt" for "c:\windows\test.txt"
 	}
+	else
+	{
+		// no path separator inside - everything in this path is a filename
+		Clear();
+	}
 }
 
 // ============================================================================
@@ -1106,14 +1107,14 @@
 {
 	if(m_pPath && m_pPath->IsShared())
 	{
-		TPath* pPath = m_pPath->Clone();
+		details::TPath* pPath = m_pPath->Clone();
 		Clear();
 		m_pPath = pPath;
 	}
 
 	// create new internal path if does not exist
 	if(!m_pPath)
-		m_pPath = TPath::New();
+		m_pPath = details::TPath::New();
 }
 
 // ============================================================================
@@ -1223,6 +1224,11 @@
 	m_vPaths.push_back(spPath);
 }
 
+void TPathContainer::Append(const TPathContainer& vPaths)
+{
+	m_vPaths.insert(m_vPaths.end(), vPaths.m_vPaths.begin(), vPaths.m_vPaths.end());
+}
+
 // ============================================================================
 /// TPathContainer::GetAt
 /// @date 2009/11/30