This commit is contained in:
Igor Pavlov
2015-06-15 00:00:00 +00:00
committed by Kornel Lesiński
parent 0713a3ab80
commit 54490d51d5
591 changed files with 34932 additions and 16390 deletions

View File

@@ -12,13 +12,41 @@ namespace NWindows {
namespace NFile {
namespace NName {
#define IS_SEPAR(c) IS_PATH_SEPAR(c)
int FindSepar(const wchar_t *s) throw()
{
for (const wchar_t *p = s;; p++)
{
const wchar_t c = *p;
if (c == 0)
return -1;
if (IS_SEPAR(c))
return (int)(p - s);
}
}
#ifndef USE_UNICODE_FSTRING
int FindSepar(const FChar *s) throw()
{
for (const FChar *p = s;; p++)
{
const FChar c = *p;
if (c == 0)
return -1;
if (IS_SEPAR(c))
return (int)(p - s);
}
}
#endif
#ifndef USE_UNICODE_FSTRING
void NormalizeDirPathPrefix(FString &dirPath)
{
if (dirPath.IsEmpty())
return;
if (dirPath.Back() != FCHAR_PATH_SEPARATOR)
dirPath += FCHAR_PATH_SEPARATOR;
if (!IsPathSepar(dirPath.Back()))
dirPath.Add_PathSepar();
}
#endif
@@ -26,26 +54,51 @@ void NormalizeDirPathPrefix(UString &dirPath)
{
if (dirPath.IsEmpty())
return;
if (dirPath.Back() != WCHAR_PATH_SEPARATOR)
dirPath += WCHAR_PATH_SEPARATOR;
if (!IsPathSepar(dirPath.Back()))
dirPath.Add_PathSepar();
}
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
#ifdef _WIN32
bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
bool IsAltPathPrefix(CFSTR s) throw()
{
unsigned len = MyStringLen(s);
if (len == 0)
return false;
if (s[len - 1] != ':')
return false;
#if defined(_WIN32) && !defined(UNDER_CE)
if (IsDevicePath(s))
return false;
if (IsSuperPath(s))
{
s += kSuperPathPrefixSize;
len -= kSuperPathPrefixSize;
}
if (len == 2 && IsDrivePath2(s))
return false;
#endif
return true;
}
#if defined(_WIN32) && !defined(UNDER_CE)
const wchar_t *kSuperPathPrefix = L"\\\\?\\";
static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\";
#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\')
#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\')
#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\')
#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
#define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
#define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))
#define IS_UNC_WITH_SLASH(s) ( \
((s)[0] == 'U' || (s)[0] == 'u') && \
((s)[1] == 'N' || (s)[1] == 'n') && \
((s)[2] == 'C' || (s)[2] == 'c') && \
(s)[3] == '\\')
((s)[0] == 'U' || (s)[0] == 'u') \
&& ((s)[1] == 'N' || (s)[1] == 'n') \
&& ((s)[2] == 'C' || (s)[2] == 'c') \
&& IS_SEPAR((s)[3]))
bool IsDevicePath(CFSTR s) throw()
{
@@ -81,50 +134,133 @@ bool IsDevicePath(CFSTR s) throw()
}
bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }
bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
#ifndef USE_UNICODE_FSTRING
bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; }
bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
#endif // USE_UNICODE_FSTRING
bool IsAbsolutePath(const wchar_t *s) throw()
bool IsNetworkPath(CFSTR s) throw()
{
return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s);
if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
return false;
if (IsSuperUncPath(s))
return true;
FChar c = s[2];
return (c != '.' && c != '?');
}
unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
{
if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
return 0;
unsigned prefixSize = 2;
if (IsSuperUncPath(s))
prefixSize = kSuperUncPathPrefixSize;
else
{
FChar c = s[2];
if (c == '.' || c == '?')
return 0;
}
int pos = FindSepar(s + prefixSize);
if (pos < 0)
return 0;
return prefixSize + pos + 1;
}
bool IsNetworkShareRootPath(CFSTR s) throw()
{
unsigned prefixSize = GetNetworkServerPrefixSize(s);
if (prefixSize == 0)
return false;
s += prefixSize;
int pos = FindSepar(s);
if (pos < 0)
return true;
return s[(unsigned)pos + 1] == 0;
}
static const unsigned kDrivePrefixSize = 3; /* c:\ */
bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
#ifndef USE_UNICODE_FSTRING
bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
#endif // USE_UNICODE_FSTRING
/*
bool IsDrivePath_SuperAllowed(CFSTR s)
{
if (IsSuperPath(s))
s += kSuperPathPrefixSize;
return IsDrivePath(s);
}
*/
bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
{
if (IsSuperPath(s))
s += kSuperPathPrefixSize;
return IsDrivePath(s) && s[kDrivePrefixSize] == 0;
}
bool IsAbsolutePath(const wchar_t *s) throw()
{
return IS_SEPAR(s[0]) || IsDrivePath2(s);
}
int FindAltStreamColon(CFSTR path)
{
unsigned i = 0;
if (IsDrivePath2(path))
i = 2;
int colonPos = -1;
for (;; i++)
{
FChar c = path[i];
if (c == 0)
return colonPos;
if (c == ':')
{
if (colonPos < 0)
colonPos = i;
continue;
}
if (IS_SEPAR(c))
colonPos = -1;
}
}
#ifndef USE_UNICODE_FSTRING
static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw()
static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
{
// Network path: we look "server\path\" as root prefix
int pos = FindCharPosInString(s, '\\');
int pos = FindSepar(s);
if (pos < 0)
return 0;
int pos2 = FindCharPosInString(s + pos + 1, '\\');
int pos2 = FindSepar(s + (unsigned)pos + 1);
if (pos2 < 0)
return 0;
return pos + pos2 + 2;
}
static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw()
static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
{
if (IsDrivePath(s))
return kDrivePrefixSize;
if (s[0] != '\\' || s[1] != '\\')
if (!IS_SEPAR(s[0]))
return 0;
if (s[1] == 0 || !IS_SEPAR(s[1]))
return 1;
unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
return (size == 0) ? 0 : 2 + size;
}
static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()
static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
{
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
{
@@ -132,13 +268,13 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw()
return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
}
// we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR);
int pos = FindSepar(s + kSuperPathPrefixSize);
if (pos < 0)
return 0;
return kSuperPathPrefixSize + pos + 1;
}
unsigned GetRootPrefixSize(CFSTR s) throw()
unsigned GetRootPrefixSize(CFSTR s)
{
if (IS_DEVICE_PATH(s))
return kDevicePathPrefixSize;
@@ -149,29 +285,31 @@ unsigned GetRootPrefixSize(CFSTR s) throw()
#endif // USE_UNICODE_FSTRING
static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()
static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)
{
// Network path: we look "server\path\" as root prefix
int pos = FindCharPosInString(s, L'\\');
int pos = FindSepar(s);
if (pos < 0)
return 0;
int pos2 = FindCharPosInString(s + pos + 1, L'\\');
int pos2 = FindSepar(s + (unsigned)pos + 1);
if (pos2 < 0)
return 0;
return pos + pos2 + 2;
}
static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()
static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)
{
if (IsDrivePath(s))
return kDrivePrefixSize;
if (s[0] != '\\' || s[1] != '\\')
if (!IS_SEPAR(s[0]))
return 0;
if (s[1] == 0 || !IS_SEPAR(s[1]))
return 1;
unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
return (size == 0) ? 0 : 2 + size;
}
static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s)
{
if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
{
@@ -179,7 +317,7 @@ static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()
return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
}
// we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\');
int pos = FindSepar(s + kSuperPathPrefixSize);
if (pos < 0)
return 0;
return kSuperPathPrefixSize + pos + 1;
@@ -196,12 +334,12 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw()
#else // _WIN32
bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR }
bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }
#ifndef USE_UNICODE_FSTRING
unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }
unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }
#endif
unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; }
unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
#endif // _WIN32
@@ -234,26 +372,26 @@ static bool GetCurDir(UString &path)
static bool ResolveDotsFolders(UString &s)
{
#ifdef _WIN32
s.Replace(L'/', WCHAR_PATH_SEPARATOR);
// s.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
for (int i = 0;;)
for (unsigned i = 0;;)
{
wchar_t c = s[i];
if (c == 0)
return true;
if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR))
if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
{
wchar_t c1 = s[i + 1];
if (c1 == '.')
{
wchar_t c2 = s[i + 2];
if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0)
if (IS_SEPAR(c2) || c2 == 0)
{
if (i == 0)
return false;
int k = i - 2;
for (; k >= 0; k--)
if (s[k] == WCHAR_PATH_SEPARATOR)
if (IS_SEPAR(s[(unsigned)k]))
break;
unsigned num;
if (k >= 0)
@@ -272,7 +410,7 @@ static bool ResolveDotsFolders(UString &s)
}
else
{
if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0)
if (IS_SEPAR(c1) || c1 == 0)
{
unsigned num = 2;
if (i != 0)
@@ -308,11 +446,11 @@ static bool AreThereDotsFolders(CFSTR s)
FChar c = s[i];
if (c == 0)
return false;
if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR))
if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
{
FChar c1 = s[i + 1];
if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR ||
(c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR)))
if (c1 == 0 || IS_SEPAR(c1) ||
(c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))
return true;
}
}
@@ -360,16 +498,16 @@ int GetUseSuperPathType(CFSTR s) throw()
if (c == '.' || c == ' ')
{
FChar c2 = s[i + 1];
if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR)
if (c2 == 0 || IS_SEPAR(c2))
{
// if it's "." or "..", it's not bad name.
if (c == '.')
{
if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)
if (i == 0 || IS_SEPAR(s[i - 1]))
continue;
if (s[i - 1] == '.')
{
if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR)
if (i - 1 == 0 || IS_SEPAR(s[i - 2]))
continue;
}
}
@@ -431,14 +569,17 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
return true;
}
if (c == CHAR_PATH_SEPARATOR)
if (IS_SEPAR(c))
{
if (s[1] == CHAR_PATH_SEPARATOR)
if (IS_SEPAR(s[1]))
{
UString temp = fs2us(s + 2);
unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);
if (fixedSize == 0) // maybe we must ignore that error to allow short network paths?
// we ignore that error to allow short network paths server\share?
/*
if (fixedSize == 0)
return false;
*/
UString rem = &temp[fixedSize];
if (!ResolveDotsFolders(rem))
return false;
@@ -451,14 +592,17 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
}
else
{
if (IsDrivePath(s))
if (IsDrivePath2(s))
{
UString temp = fs2us(s);
UString rem = &temp[kDrivePrefixSize];
unsigned prefixSize = 2;
if (IsDrivePath(s))
prefixSize = kDrivePrefixSize;
UString rem = temp.Ptr(prefixSize);
if (!ResolveDotsFolders(rem))
return true;
res += kSuperPathPrefix;
temp.DeleteFrom(kDrivePrefixSize);
temp.DeleteFrom(prefixSize);
res += temp;
res += rem;
return true;
@@ -468,8 +612,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
UString curDir;
if (!GetCurDir(curDir))
return false;
if (curDir.Back() != WCHAR_PATH_SEPARATOR)
curDir += WCHAR_PATH_SEPARATOR;
NormalizeDirPathPrefix(curDir);
unsigned fixedSizeStart = 0;
unsigned fixedSize = 0;
@@ -489,10 +632,10 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
}
else
{
if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR)
if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
return false;
fixedSizeStart = 2;
fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);
fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
if (fixedSize == 0)
return false;
superMarker = kSuperUncPrefix;
@@ -500,7 +643,7 @@ static bool GetSuperPathBase(CFSTR s, UString &res)
}
UString temp;
if (c == CHAR_PATH_SEPARATOR)
if (IS_SEPAR(c))
{
temp = fs2us(s + 1);
}
@@ -584,7 +727,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
#ifdef UNDER_CE
if (s[0] != CHAR_PATH_SEPARATOR)
if (!IS_SEPAR(s[0]))
{
if (!dirPrefix)
return false;
@@ -614,7 +757,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
return true;
if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
return true;
if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR)
if (IS_SEPAR(c) && IS_SEPAR(s[1]))
return true;
if (IsDrivePath(s))
return true;
@@ -628,8 +771,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
if (!GetCurDir(curDir))
return false;
}
if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR)
curDir += WCHAR_PATH_SEPARATOR;
NormalizeDirPathPrefix(curDir);
unsigned fixedSize = 0;
@@ -647,9 +789,9 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
fixedSize = kDrivePrefixSize;
else
{
if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR)
if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
return false;
fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]);
fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
if (fixedSize == 0)
return false;
fixedSize += 2;
@@ -659,7 +801,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
#endif // _WIN32
UString temp;
if (s[0] == CHAR_PATH_SEPARATOR)
if (IS_SEPAR(s[0]))
{
temp = fs2us(s + 1);
}