Changeset View
Changeset View
Standalone View
Standalone View
source/lib/file/vfs/vfs_util.cpp
/* Copyright (C) 2015 Wildfire Games. | /* Copyright (C) 2019 Wildfire Games. | ||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* "Software"), to deal in the Software without restriction, including | * "Software"), to deal in the Software without restriction, including | ||||
* without limitation the rights to use, copy, modify, merge, publish, | * without limitation the rights to use, copy, modify, merge, publish, | ||||
* distribute, sublicense, and/or sell copies of the Software, and to | * distribute, sublicense, and/or sell copies of the Software, and to | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
* | * | ||||
* The above copyright notice and this permission notice shall be included | * The above copyright notice and this permission notice shall be included | ||||
* in all copies or substantial portions of the Software. | * in all copies or substantial portions of the Software. | ||||
* | * | ||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
*/ | */ | ||||
/* | |||||
* helper functions for directory access | |||||
*/ | |||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "lib/file/vfs/vfs_util.h" | #include "lib/file/vfs/vfs_util.h" | ||||
#include <cstdio> | #include <cstdio> | ||||
#include <cstring> | #include <cstring> | ||||
#include <queue> | #include <queue> | ||||
#include "lib/regex.h" | #include "lib/regex.h" | ||||
#include "lib/sysdep/filesystem.h" | #include "lib/sysdep/filesystem.h" | ||||
namespace vfs { | namespace vfs { | ||||
Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, VfsPaths& pathnames) | Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, VfsPaths& pathnames, bool sorted) | ||||
{ | { | ||||
std::vector<CFileInfo> files; | std::vector<CFileInfo> files; | ||||
RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, 0)); | RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, 0)); | ||||
pathnames.clear(); | pathnames.clear(); | ||||
pathnames.reserve(files.size()); | pathnames.reserve(files.size()); | ||||
for(size_t i = 0; i < files.size(); i++) | for(size_t i = 0; i < files.size(); i++) | ||||
{ | { | ||||
if(match_wildcard(files[i].Name().string().c_str(), filter)) | if(match_wildcard(files[i].Name().string().c_str(), filter)) | ||||
pathnames.push_back(path / files[i].Name()); | pathnames.push_back(path / files[i].Name()); | ||||
} | } | ||||
if (sorted) | |||||
std::sort(pathnames.begin(), pathnames.end()); | |||||
vladislavbelov: We can add `std::shuffle` here on the testing stage to detect possible errors. | |||||
return INFO::OK; | return INFO::OK; | ||||
} | } | ||||
Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags, DirCallback dircb, uintptr_t dircbData) | Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags, DirCallback dircb, uintptr_t dircbData) | ||||
{ | { | ||||
// (declare here to avoid reallocations) | // (declare here to avoid reallocations) | ||||
CFileInfos files; | CFileInfos files; | ||||
DirectoryNames subdirectoryNames; | DirectoryNames subdirectoryNames; | ||||
// (a FIFO queue is more efficient than recursion because it uses less | // (a FIFO queue is more efficient than recursion because it uses less | ||||
// stack space and avoids seeks due to breadth-first traversal.) | // stack space and avoids seeks due to breadth-first traversal.) | ||||
Show All 24 Lines | while(!pendingDirectories.empty()) | ||||
for(size_t i = 0; i < subdirectoryNames.size(); i++) | for(size_t i = 0; i < subdirectoryNames.size(); i++) | ||||
pendingDirectories.push(path / subdirectoryNames[i]/""); | pendingDirectories.push(path / subdirectoryNames[i]/""); | ||||
pendingDirectories.pop(); | pendingDirectories.pop(); | ||||
} | } | ||||
return INFO::OK; | return INFO::OK; | ||||
} | } | ||||
void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t& nextNumber, VfsPath& nextPathname) | void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t& nextNumber, VfsPath& nextPathname) | ||||
{ | { | ||||
// (first call only:) scan directory and set nextNumber according to | // (first call only:) scan directory and set nextNumber according to | ||||
// highest matching filename found. this avoids filling "holes" in | // highest matching filename found. this avoids filling "holes" in | ||||
// the number series due to deleted files, which could be confusing. | // the number series due to deleted files, which could be confusing. | ||||
// example: add 1st and 2nd; [exit] delete 1st; [restart] | // example: add 1st and 2nd; [exit] delete 1st; [restart] | ||||
// add 3rd -> without this measure it would get number 1, not 3. | // add 3rd -> without this measure it would get number 1, not 3. | ||||
if(nextNumber == 0) | if(nextNumber == 0) | ||||
Show All 32 Lines |
Wildfire Games · Phabricator
We can add std::shuffle here on the testing stage to detect possible errors.