#include "FileSystem.h"
#include "Locale.h"
#include "Stream/FileStream.h"
#include "Stream/Accessor.h"
#if defined VCZH_MSVC
#include <Windows.h>
#include <Shlwapi.h>
#pragma comment(lib,
"Shlwapi.lib"
)
#elif defined VCZH_GCC
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#endif
namespace
{
namespace
{
using
namespace
collections
;
using
namespace
stream
;
#if defined VCZH_GCC
const wchar_t FilePath::Delimiter;
#endif
void
::
()
{
{
<
wchar_t
>
(
.
() +
1
);
#if defined VCZH_MSVC
(&
buffer
0
],
.
() +
1
,
.
());
#elif defined VCZH_GCC
wcscpy(&buffer[0], fullPath.Buffer());
#endif
for
(
=
0
;
i
<
buffer
.
();
i
++)
{
if
(
buffer
i
] ==
L'\\'
||
buffer
i
] ==
L'/'
)
{
buffer
i
] =
;
}
}
= &
buffer
0
];
}
#if defined VCZH_MSVC
if
(
!=
L""
)
{
if
(
.
() <
2
||
1
] !=
L':'
)
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
wchar_t
[
260
+
1
] = {
0
};
auto result = GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer);
auto
=
(
sizeof
(
buffer
) /
sizeof
(*
buffer
),
buffer
);
if (result > MAX_PATH + 1 || result == 0)
if
(
result
>
260
+
1
||
result
==
0
)
{
throw
(
L"Failed to call GetCurrentDirectory."
,
L"vl::filesystem::FilePath::Initialize"
,
L""
);
}
=
(
buffer
) +
L"\\"
+
;
}
{
wchar_t buffer[MAX_PATH + 1] = { 0 };
wchar_t
[
260
+
1
] = {
0
};
if
(
.
() ==
2
&&
1
] ==
L':'
)
{
+=
L"\\"
;
}
auto result = GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL);
auto
=
(
.
(),
sizeof
(
buffer
) /
sizeof
(*
buffer
),
buffer
,
0
);
if (result > MAX_PATH + 1 || result == 0)
if
(
result
>
260
+
1
||
result
==
0
)
{
throw
(
L"The path is illegal."
,
L"vl::filesystem::FilePath::FilePath"
,
L"_filePath"
);
}
{
wchar_t shortPath[MAX_PATH + 1];
wchar_t longPath[MAX_PATH + 1];
if (GetShortPathName(buffer, shortPath, MAX_PATH) > 0)
if
(
(
buffer
,
shortPath
,
260
) >
0
)
{
if (GetLongPathName(shortPath, longPath, MAX_PATH) > 0)
if
(
(
shortPath
,
longPath
,
260
) >
0
)
{
(
buffer
,
longPath
,
sizeof
(
buffer
));
}
}
}
=
buffer
;
}
}
#elif defined VCZH_GCC
if (fullPath.Length() == 0)
fullPath = L"/";
if (fullPath[0] != Delimiter)
{
char buffer[PATH_MAX] = { 0 };
getcwd(buffer, PATH_MAX);
fullPath = atow(AString(buffer)) + Delimiter + fullPath;
}
{
collections::List<WString> components;
GetPathComponents(fullPath, components);
for(int i = 0; i < components.Count(); i++)
{
if(components[i] == L".")
{
components.RemoveAt(i);
i--;
}
else if(components[i] == L"..")
{
if(i > 0)
{
components.RemoveAt(i);
components.RemoveAt(i - 1);
i -= 2;
}
else
{
throw ArgumentException(L"Illegal path.");
}
}
}
fullPath = ComponentsToPath(components);
}
#endif
if
(
!=
L"/"
&&
.
() >
0
&&
.
() -
1
] ==
)
{
.
(
.
() -
1
);
}
}
::
()
{
}
::
(
const
&
)
:fullPath(
)
{
();
}
::
(
const
wchar_t
*
)
:fullPath(
)
{
();
}
::
(
const
&
)
:fullPath(
.
)
{
}
::
()
{
}
::
(
const
&
,
const
&
)
{
return
::
(
.
,
.
);
}
::
(
const
&
)
const
{
if
(
())
{
return
;
}
else
{
return
+
L"/"
+
;
}
}
bool
::
()
const
{
#if defined VCZH_MSVC
WIN32_FILE_ATTRIBUTE_DATA
;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if
(!
result
)
return
false
;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
return
(
info
.
&
0x00000010
) ==
0
;
#elif defined VCZH_GCC
struct stat info;
AString path = wtoa(fullPath);
int result = stat(path.Buffer(), &info);
if(result != 0) return false;
else return S_ISREG(info.st_mode);
#endif
}
bool
::
()
const
{
#if defined VCZH_MSVC
WIN32_FILE_ATTRIBUTE_DATA
;
BOOL result = GetFileAttributesEx(fullPath.Buffer(), GetFileExInfoStandard, &info);
if
(!
result
)
return
false
;
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
return
(
info
.
&
0x00000010
) !=
0
;
#elif defined VCZH_GCC
struct stat info;
AString path = wtoa(fullPath);
int result = stat(path.Buffer(), &info);
if(result != 0) return false;
else return S_ISDIR(info.st_mode);
#endif
}
bool
::
()
const
{
#if defined VCZH_MSVC
return
L""
;
#elif defined VCZH_GCC
return fullPath == L"/";
#endif
}
::
()
const
{
=
;
auto index = INVLOC.FindLast(fullPath, delimiter, Locale::None);
auto
=
vl
::
::
().
(
,
delimiter
,
::
);
if
(
index
.
== -
1
)
return
;
return
.
(
.
() -
index
.
-
1
);
}
::
()
const
{
=
;
auto index = INVLOC.FindLast(fullPath, delimiter, Locale::None);
auto
=
vl
::
::
().
(
,
delimiter
,
::
);
if
(
index
.
== -
1
)
return
();
return
.
(
index
.
);
}
::
()
const
{
return
;
}
::
(
const
&
)
{
if
(
.
()==
0
||
.
.
()==
0
||
0
] !=
.
0
])
{
return
.
;
}
#if defined VCZH_MSVC
wchar_t buffer[MAX_PATH + 1] = { 0 };
wchar_t
[
260
+
1
] = {
0
};
buffer
,
.
(),
(IsFolder() ? FILE_ATTRIBUTE_DIRECTORY : 0),
.
.
(),
(_filePath.IsFolder() ? FILE_ATTRIBUTE_DIRECTORY : 0)
);
return
buffer
;
#elif defined VCZH_GCC
collections::List<WString> srcComponents, tgtComponents, resultComponents;
GetPathComponents(IsFolder() ? fullPath : GetFolder().GetFullPath(), srcComponents);
GetPathComponents(_filePath.fullPath, tgtComponents);
int minLength = srcComponents.Count() <= tgtComponents.Count() ? srcComponents.Count() : tgtComponents.Count();
int lastCommonComponent = 0;
for(int i = 0; i < minLength; i++)
{
if(srcComponents[i] == tgtComponents[i])
{
lastCommonComponent = i;
}
else
break;
}
for(int i = lastCommonComponent + 1; i < srcComponents.Count(); i++)
{
resultComponents.Add(L"..");
}
for(int i = lastCommonComponent + 1; i < tgtComponents.Count(); i++)
{
resultComponents.Add(tgtComponents[i]);
}
return ComponentsToPath(resultComponents);
#endif
}
void
::
(
,
collections
::
<
>&
)
{
=
;
=
;
.
();
while
(
true
)
{
auto index = INVLOC.FindFirst(pathRemaining, delimiter, Locale::None);
auto
=
vl
::
::
().
(
pathRemaining
,
delimiter
,
::
);
if
(
index
.
== -
1
)
break
;
if
(
index
.
!=
0
)
.
(
pathRemaining
.
(
index
.
));
else
{
#if defined VCZH_GCC
// Unix absolute path starting with "/"
// components[0] will be L"/"
components.Add(delimiter);
#elif defined VCZH_MSVC
if
(
pathRemaining
.
() >=
2
&&
pathRemaining
1
] ==
)
{
.
(
L"\\"
);
index
.
++;
}
#endif
}
pathRemaining
pathRemaining
.
(
pathRemaining
.
() - (
index
.
+
index
.
));
}
if
(
pathRemaining
.
() !=
0
)
{
.
(
pathRemaining
);
}
}
::
(
const
collections
::
<
>&
)
{
;
=
;
int
=
0
;
#if defined VCZH_GCC
// For Unix-like OSes, if first component is "/" then take it as absolute path
if(components.Count() > 0 && components[0] == delimiter)
{
result += delimiter;
i++;
}
#elif defined VCZH_MSVC
if
(
.
() >
0
&&
0
] ==
L"\\"
)
{
result
delimiter
;
i
++;
}
#endif
for
(;
i
<
.
();
i
++)
{
result
i
];
if
(
i
+
1
<
.
())
result
delimiter
;
}
return
result
;
}
::
()
{
}
::
(
const
&
)
:filePath(
)
{
}
::
()
{
}
const
&
::
()
const
{
return
;
}
bool
::
ReadAllTextWithEncodingTesting
(
&
,
stream
::
::
&
,
bool
&
)
{
<
unsigned
char
>
;
{
(
.
(),
::
);
if
(!
fileStream
.
())
return
false
;
if
(
fileStream
.
() ==
0
)
{
=
L""
;
=
::
;
=
false
;
return
true
;
}
buffer
.
((
)
fileStream
.
());
=
fileStream
.
(&
buffer
0
],
buffer
.
());
CHECK_ERROR(count == buffer.Count(), L"vl::filesystem::File::ReadAllTextWithEncodingTesting(WString&, BomEncoder::Encoding&, bool&)#Failed to read the whole file.");
do
{
if
(!(
count
==
buffer
.
()))
throw
(
L"vl::filesystem::File::ReadAllTextWithEncodingTesting(WString&, BomEncoder::Encoding&, bool&)#Failed to read the whole file."
);}
while
(
0
);
}
(&
buffer
0
],
buffer
.
(),
,
);
(&
buffer
0
],
buffer
.
());
if
(
)
{
;
(
memoryStream
,
decoder
);
(
decoderStream
);
reader
.
();
}
else
{
switch
(
)
{
case
::
:
{
;
(
memoryStream
,
decoder
);
(
decoderStream
);
reader
.
();
}
break
;
case
::
:
{
;
(
memoryStream
,
decoder
);
(
decoderStream
);
reader
.
();
}
break
;
case
::
:
{
;
(
memoryStream
,
decoder
);
(
decoderStream
);
reader
.
();
}
break
;
default
:
{
;
(
memoryStream
,
decoder
);
(
decoderStream
);
reader
.
();
}
}
}
return
true
;
}
::
()
const
{
;
(
text
);
return
text
;
}
bool
::
(
&
)
const
{
(
.
(),
::
);
if
(!
fileStream
.
())
return
false
;
;
(
fileStream
,
decoder
);
(
decoderStream
);
reader
.
();
return
true
;
}
bool
::
(
collections
::
<
>&
)
const
{
(
.
(),
::
);
if
(!
fileStream
.
())
return
false
;
;
(
fileStream
,
decoder
);
(
decoderStream
);
while
(!
reader
.
())
{
.
(
reader
.
());
}
return
true
;
}
bool
::
(
const
&
,
bool
,
stream
::
::
)
{
(
.
(),
::
);
if
(!
fileStream
.
())
return
false
;
*
=
nullptr
;
if
(
)
{
encoder
=
new
(
);
}
else
switch
(
)
{
case
::
:
encoder
=
new
;
break
;
case
::
:
encoder
=
new
;
break
;
case
::
:
encoder
=
new
;
break
;
default
:
encoder
=
new
;
break
;
}
{
(
fileStream
, *
encoder
);
(
encoderStream
);
writer
.
(
);
}
delete
encoder
;
return
true
;
}
bool
::
(
collections
::
<
>&
,
bool
,
stream
::
::
)
{
(
.
(),
::
);
if
(!
fileStream
.
())
return
false
;
*
=
nullptr
;
if
(
)
{
encoder
=
new
(
);
}
else
switch
(
)
{
case
::
:
encoder
=
new
;
break
;
case
::
:
encoder
=
new
;
break
;
case
::
:
encoder
=
new
;
break
;
default
:
encoder
=
new
;
break
;
}
{
(
fileStream
, *
encoder
);
(
encoderStream
);
FOREACH(WString, line, lines)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
line
);)
{
writer
.
(
line
);
}
}
delete
encoder
;
return
true
;
}
bool
::
()
const
{
return
.
();
}
bool
::
()
const
{
#if defined VCZH_MSVC
return DeleteFile(filePath.GetFullPath().Buffer()) != 0;
#elif defined VCZH_GCC
AString path = wtoa(filePath.GetFullPath());
return unlink(path.Buffer()) == 0;
#endif
}
bool
::
(
const
&
)
const
{
#if defined VCZH_MSVC
=
.
();
= (
.
()
).
();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
return
(
oldFileName
.
(),
newFileName
.
()) !=
0
;
#elif defined VCZH_GCC
AString oldFileName = wtoa(filePath.GetFullPath());
AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath());
return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0;
#endif
}
::
()
{
}
::
(
const
&
)
:filePath(
)
{
}
::
()
{
}
const
&
::
()
const
{
return
;
}
bool
::
(
collections
::
<
>&
)
const
{
#if defined VCZH_MSVC
if
(
.
())
{
auto bufferSize = GetLogicalDriveStrings(0, nullptr);
if
(
bufferSize
>
0
)
{
<
wchar_t
>
(
bufferSize
);
if (GetLogicalDriveStrings((DWORD)buffer.Count(), &buffer[0]) > 0)
if
(
((
)
buffer
.
(), &
buffer
0
]) >
0
)
{
auto
= &
buffer
0
];
auto
=
begin
+
buffer
.
();
while
(
begin
<
end
&& *
begin
)
{
=
begin
;
begin
+=
driveString
.
() +
1
;
.
(
(
(
driveString
)));
}
return
true
;
}
}
return
false
;
}
else
{
if
(!
())
return
false
;
;
HANDLE findHandle = INVALID_HANDLE_VALUE;
while
(
true
)
{
if (findHandle == INVALID_HANDLE_VALUE)
if
(
findHandle
== ((
)(
)-
1
))
{
= (
/
L"*"
).GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
findHandle
=
(
searchPath
.
(), &
findData
);
if (findHandle == INVALID_HANDLE_VALUE)
if
(
findHandle
== ((
)(
)-
1
))
{
break
;
}
}
else
{
BOOL result = FindNextFile(findHandle, &findData);
=
(
findHandle
, &
findData
);
if
(
result
==
0
)
{
(
findHandle
);
break
;
}
}
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
if
(
findData
.
&
0x00000010
)
{
if
(
(
findData
.
,
L"."
) !=
0
&&
(
findData
.
,
L".."
) !=
0
)
{
.
(
(
/
findData
.
));
}
}
}
return
true
;
}
#elif defined VCZH_GCC
if (!Exists()) return false;
DIR *dir;
AString searchPath = wtoa(filePath.GetFullPath());
if ((dir = opendir(searchPath.Buffer())) == NULL)
{
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
WString childName = atow(AString(entry->d_name));
FilePath childFullPath = filePath / childName;
if (childName != L"." && childName != L".." && childFullPath.IsFolder())
{
folders.Add(Folder(childFullPath));
}
}
if (closedir(dir) != 0)
{
return false;
}
return true;
#endif
}
bool
::
(
collections
::
<
>&
)
const
{
#if defined VCZH_MSVC
if
(
.
())
{
return
true
;
}
if
(!
())
return
false
;
;
HANDLE findHandle = INVALID_HANDLE_VALUE;
while
(
true
)
{
if (findHandle == INVALID_HANDLE_VALUE)
if
(
findHandle
== ((
)(
)-
1
))
{
= (
/
L"*"
).GetFullPath();
findHandle = FindFirstFile(searchPath.Buffer(), &findData);
findHandle
=
(
searchPath
.
(), &
findData
);
if (findHandle == INVALID_HANDLE_VALUE)
if
(
findHandle
== ((
)(
)-
1
))
{
break
;
}
}
else
{
BOOL result = FindNextFile(findHandle, &findData);
=
(
findHandle
, &
findData
);
if
(
result
==
0
)
{
(
findHandle
);
break
;
}
}
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
if
(!(
findData
.
&
0x00000010
))
{
.
(
(
/
findData
.
));
}
}
return
true
;
#elif defined VCZH_GCC
if (!Exists()) return false;
DIR *dir;
AString searchPath = wtoa(filePath.GetFullPath());
if ((dir = opendir(searchPath.Buffer())) == NULL)
{
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
FilePath childFullPath = filePath / (atow(AString(entry->d_name)));
if (childFullPath.IsFile())
{
files.Add(File(childFullPath));
}
}
if (closedir(dir) != 0)
{
return false;
}
return true;
#endif
}
bool
::
()
const
{
return
.
();
}
bool
::
(
bool
)
const
{
if
(
)
{
auto
=
.
();
if
(
folder
.
())
return
false
;
if
(
folder
.
())
return
(
false
);
return
(
folder
).
(
true
) &&
(
false
);
}
else
{
#if defined VCZH_MSVC
return CreateDirectory(filePath.GetFullPath().Buffer(), NULL) != 0;
#elif defined VCZH_GCC
AString path = wtoa(filePath.GetFullPath());
return mkdir(path.Buffer(), 0777) == 0;
#endif
}
}
bool
::
(
bool
)
const
{
if
(!
())
return
false
;
if
(
)
{
<
>
;
(
folders
);
FOREACH(Folder, folder, folders)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
folders
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
folder
);)
{
if
(!
folder
.
(
true
))
return
false
;
}
<
>
;
(
files
);
FOREACH(File, file, files)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
files
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
file
);)
{
if
(!
file
.
())
return
false
;
}
return
(
false
);
}
#if defined VCZH_MSVC
return RemoveDirectory(filePath.GetFullPath().Buffer()) != 0;
#elif defined VCZH_GCC
AString path = wtoa(filePath.GetFullPath());
return rmdir(path.Buffer()) == 0;
#endif
}
bool
::
(
const
&
)
const
{
#if defined VCZH_MSVC
=
.
();
= (
.
()
).
();
return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0;
return
(
oldFileName
.
(),
newFileName
.
()) !=
0
;
#elif defined VCZH_GCC
AString oldFileName = wtoa(filePath.GetFullPath());
AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath());
return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0;
#endif
}
}
}