You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/CryCommonTools/FileUtil.cpp

176 lines
4.8 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include <platform.h>
#include "FileUtil.h"
#include "PathHelpers.h"
#include "StringHelpers.h"
#include <AzFramework/IO/LocalFileIO.h>
#include <AzCore/std/functional.h>
//////////////////////////////////////////////////////////////////////////
// returns true if 'dir' is a subdirectory of 'baseDir' or same directory as 'baseDir'
// note: returns false in case of wrong names passed
static bool IsSubdirOrSameDir(const char* dir, const char* baseDir)
{
AZ::IO::LocalFileIO localFileIO;
char szFullPathDir[AZ_MAX_PATH_LEN];
if(!localFileIO.ConvertToAbsolutePath(dir, szFullPathDir, sizeof(szFullPathDir)))
{
return false;
}
char szFullPathBaseDir[2 * 1024];
if(!localFileIO.ConvertToAbsolutePath(baseDir, szFullPathBaseDir, sizeof(szFullPathBaseDir)))
{
return false;
}
const char* p = szFullPathDir;
const char* q = szFullPathBaseDir;
for (;; ++p, ++q)
{
if (tolower(*p) == tolower(*q))
{
if (*p == 0)
{
// dir is exactly same as baseDir
return true;
}
continue;
}
if ((*p == '/' || *p == '\\') && (*q == '/' || *q == '\\'))
{
continue;
}
if (*p == 0)
{
// dir length is shorter than baseDir length. so it's not a subdir
return false;
}
if (*q == 0)
{
// baseDir is shorter than dir. so may be it's a subdir.
const bool isSubdir = (*p == '/' || *p == '\\');
return isSubdir;
}
return false;
}
}
//////////////////////////////////////////////////////////////////////////
// the paths must have trailing slash
static bool ScanDirectoryRecursive(const string& root, const string& path, const string& file, std::vector<string>& files, bool recursive, const string& dirToIgnore)
{
bool anyFound = false;
if (!dirToIgnore.empty())
{
if (IsSubdirOrSameDir(root.c_str(), dirToIgnore.c_str()))
{
return anyFound;
}
}
AZ::IO::LocalFileIO localFileIO;
localFileIO.FindFiles(root.c_str(), file.c_str(), [&](const char* filePath) -> bool
{
bool isDir = localFileIO.IsDirectory(filePath);
if (!isDir)
{
const string foundFilename(filePath);
if (StringHelpers::MatchesWildcardsIgnoreCase(foundFilename, file))
{
anyFound = true;
files.push_back(PathHelpers::Join(path, PathHelpers::GetFilename(filePath)));
}
}
return true; // Keep iterating
});
if (recursive)
{
localFileIO.FindFiles(root.c_str(), "*", [&](const char* filePath) -> bool
{
bool isDir = localFileIO.IsDirectory(filePath);
// If recursive.
if (isDir && strcmp(filePath, ".") && strcmp(filePath, ".."))
{
if (ScanDirectoryRecursive(filePath, PathHelpers::Join(path, PathHelpers::GetFilename(filePath)), file, files, recursive, dirToIgnore))
{
anyFound = true;
}
}
return true; // Keep iterating
});
}
return anyFound;
}
//////////////////////////////////////////////////////////////////////////
bool FileUtil::ScanDirectory(const string& path, const string& file, std::vector<string>& files, bool recursive, const string& dirToIgnore)
{
return ScanDirectoryRecursive(path, "", file, files, recursive, dirToIgnore);
}
bool FileUtil::EnsureDirectoryExists(const char* szPathIn)
{
if (!szPathIn || !szPathIn[0])
{
return true;
}
if (DirectoryExists(szPathIn))
{
return true;
}
std::vector<char> path(szPathIn, szPathIn + strlen(szPathIn) + 1);
char* p = &path[0];
// Skip '/' and '//' in the beginning
while (*p == '/' || *p == '\\')
{
++p;
}
for (;; )
{
while (*p != '/' && *p != '\\' && *p)
{
++p;
}
const char saved = *p;
*p = 0;
AZ::IO::LocalFileIO().CreatePath(&path[0]);
*p++ = saved;
if (saved == 0)
{
break;
}
}
return DirectoryExists(szPathIn);
}