diff --git a/src/ScenarioRepository.cpp b/src/ScenarioRepository.cpp index a9b6bdf381..bd4a0c4fc8 100644 --- a/src/ScenarioRepository.cpp +++ b/src/ScenarioRepository.cpp @@ -246,13 +246,14 @@ private: String::Set(pattern, sizeof(pattern), directory); Path::Append(pattern, sizeof(pattern), "*.sc6"); - auto fileEnumerator = FileEnumerator(pattern, true); - while (fileEnumerator.Next()) + IFileScanner * scanner = Path::ScanDirectory(pattern, true); + while (scanner->Next()) { - auto path = fileEnumerator.GetPath(); - auto fileInfo = fileEnumerator.GetFileInfo(); + auto path = scanner->GetPath(); + auto fileInfo = scanner->GetFileInfo(); AddScenario(path, fileInfo->last_modified); } + delete scanner; } void AddScenario(const utf8 * path, uint64 timestamp) diff --git a/src/core/FileEnumerator.cpp b/src/core/FileEnumerator.cpp index c934d779c3..c21243f6a8 100644 --- a/src/core/FileEnumerator.cpp +++ b/src/core/FileEnumerator.cpp @@ -14,6 +14,7 @@ *****************************************************************************/ #pragma endregion +#include #include "FileEnumerator.h" #include "Memory.hpp" #include "Path.hpp" @@ -24,135 +25,172 @@ extern "C" #include "../platform/platform.h" } -FileEnumerator::FileEnumerator(const utf8 * pattern, bool recurse) +class FileScanner : public IFileScanner { - _rootPath = Memory::Allocate(MAX_PATH); - Path::GetDirectory(_rootPath, MAX_PATH, pattern); - _pattern = String::Duplicate(Path::GetFileName(pattern)); - _recurse = recurse; - - _fileInfo = Memory::Allocate(); - Memory::Set(_fileInfo, 0, sizeof(file_info)); - _path = Memory::Allocate(MAX_PATH); - - _fileHandle = INVALID_HANDLE; - - Reset(); -} - -FileEnumerator::~FileEnumerator() -{ - CloseHandles(); - Memory::Free(_path); - Memory::Free(_fileInfo); - Memory::Free(_pattern); - Memory::Free(_rootPath); -} - -void FileEnumerator::Reset() -{ - CloseHandles(); - - DirectoryState directoryState; - directoryState.Directory = String::Duplicate(_rootPath); - directoryState.Handle = INVALID_HANDLE; - _directoryStack.push(directoryState); -} - -bool FileEnumerator::Next() -{ - while (true) +private: + struct DirectoryState { - while (_fileHandle == INVALID_HANDLE) + utf8 * Directory; + int Handle; + }; + + // Enumeration options + utf8 * _rootPath; + utf8 * _pattern; + bool _recurse; + + // Enumeration state + int _fileHandle; + std::stack _directoryStack; + + // Current enumeration + file_info * _fileInfo; + utf8 * _path; + +public: + FileScanner(const utf8 * pattern, bool recurse) + { + _rootPath = Memory::Allocate(MAX_PATH); + Path::GetDirectory(_rootPath, MAX_PATH, pattern); + _pattern = String::Duplicate(Path::GetFileName(pattern)); + _recurse = recurse; + + _fileInfo = Memory::Allocate(); + Memory::Set(_fileInfo, 0, sizeof(file_info)); + _path = Memory::Allocate(MAX_PATH); + + _fileHandle = INVALID_HANDLE; + + Reset(); + } + + ~FileScanner() override + { + CloseHandles(); + Memory::Free(_path); + Memory::Free(_fileInfo); + Memory::Free(_pattern); + Memory::Free(_rootPath); + } + + const file_info * GetFileInfo() const override + { + return _fileInfo; + } + + const utf8 * GetPath() const override + { + return _path; + } + + void Reset() override + { + CloseHandles(); + + DirectoryState directoryState; + directoryState.Directory = String::Duplicate(_rootPath); + directoryState.Handle = INVALID_HANDLE; + _directoryStack.push(directoryState); + } + + bool Next() override + { + while (true) { - if (_directoryStack.size() == 0) + while (_fileHandle == INVALID_HANDLE) { - return false; - } - - DirectoryState directoryState = _directoryStack.top(); - if (directoryState.Handle == INVALID_HANDLE) - { - // Start enumerating files for this directory - utf8 pattern[MAX_PATH]; - String::Set(pattern, sizeof(pattern), directoryState.Directory); - Path::Append(pattern, sizeof(pattern), _pattern); - - _fileHandle = platform_enumerate_files_begin(pattern); - break; - } - else - { - // Next directory - utf8 name[MAX_PATH]; - if (platform_enumerate_directories_next(directoryState.Handle, name)) + if (_directoryStack.size() == 0) { - DirectoryState newDirectoryState; - newDirectoryState.Handle = INVALID_HANDLE; - newDirectoryState.Directory = Memory::Allocate(MAX_PATH); - - String::Set(newDirectoryState.Directory, MAX_PATH, directoryState.Directory); - Path::Append(newDirectoryState.Directory, MAX_PATH, name); - - _directoryStack.push(newDirectoryState); + return false; } - else + + DirectoryState directoryState = _directoryStack.top(); + if (directoryState.Handle == INVALID_HANDLE) { - platform_enumerate_directories_end(directoryState.Handle); - Memory::Free(directoryState.Directory); + // Start enumerating files for this directory + utf8 pattern[MAX_PATH]; + String::Set(pattern, sizeof(pattern), directoryState.Directory); + Path::Append(pattern, sizeof(pattern), _pattern); + + _fileHandle = platform_enumerate_files_begin(pattern); + break; + } else + { + // Next directory + utf8 name[MAX_PATH]; + if (platform_enumerate_directories_next(directoryState.Handle, name)) + { + DirectoryState newDirectoryState; + newDirectoryState.Handle = INVALID_HANDLE; + newDirectoryState.Directory = Memory::Allocate(MAX_PATH); + + String::Set(newDirectoryState.Directory, MAX_PATH, directoryState.Directory); + Path::Append(newDirectoryState.Directory, MAX_PATH, name); + + _directoryStack.push(newDirectoryState); + } else + { + platform_enumerate_directories_end(directoryState.Handle); + Memory::Free(directoryState.Directory); + _directoryStack.pop(); + } + } + } + + // Next file + if (_fileHandle != INVALID_HANDLE) + { + if (platform_enumerate_files_next(_fileHandle, _fileInfo)) + { + String::Set(_path, MAX_PATH, _directoryStack.top().Directory); + Path::Append(_path, MAX_PATH, _fileInfo->path); + return true; + } + platform_enumerate_files_end(_fileHandle); + _fileHandle = INVALID_HANDLE; + } + + if (_recurse) + { + // Start enumerating sub-directories + DirectoryState * directoryState = &_directoryStack.top(); + directoryState->Handle = platform_enumerate_directories_begin(directoryState->Directory); + if (directoryState->Handle == INVALID_HANDLE) + { + Memory::Free(directoryState->Directory); _directoryStack.pop(); } + } else + { + Memory::Free(_directoryStack.top().Directory); + _directoryStack.pop(); + return false; } } + } - // Next file +private: + void CloseHandles() + { if (_fileHandle != INVALID_HANDLE) { - if (platform_enumerate_files_next(_fileHandle, _fileInfo)) - { - String::Set(_path, MAX_PATH, _directoryStack.top().Directory); - Path::Append(_path, MAX_PATH, _fileInfo->path); - return true; - } platform_enumerate_files_end(_fileHandle); _fileHandle = INVALID_HANDLE; } - - if (_recurse) + while (_directoryStack.size() > 0) { - // Start enumerating sub-directories - DirectoryState * directoryState = &_directoryStack.top(); - directoryState->Handle = platform_enumerate_directories_begin(directoryState->Directory); - if (directoryState->Handle == INVALID_HANDLE) + DirectoryState directoryState = _directoryStack.top(); + if (directoryState.Handle != INVALID_HANDLE) { - Memory::Free(directoryState->Directory); - _directoryStack.pop(); + platform_enumerate_directories_end(directoryState.Handle); } - } - else - { - Memory::Free(_directoryStack.top().Directory); + Memory::Free(directoryState.Directory); _directoryStack.pop(); - return false; } } -} +}; -void FileEnumerator::CloseHandles() +IFileScanner * Path::ScanDirectory(const utf8 * pattern, bool recurse) { - if (_fileHandle != INVALID_HANDLE) - { - platform_enumerate_files_end(_fileHandle); - _fileHandle = INVALID_HANDLE; - } - while (_directoryStack.size() > 0) - { - DirectoryState directoryState = _directoryStack.top(); - if (directoryState.Handle != INVALID_HANDLE) - { - platform_enumerate_directories_end(directoryState.Handle); - } - Memory::Free(directoryState.Directory); - _directoryStack.pop(); - } + return new FileScanner(pattern, recurse); } diff --git a/src/core/FileEnumerator.h b/src/core/FileEnumerator.h index 1c854acb35..7a14330ae5 100644 --- a/src/core/FileEnumerator.h +++ b/src/core/FileEnumerator.h @@ -16,42 +16,22 @@ #pragma once -#include #include "../common.h" struct file_info; -class FileEnumerator final + +interface IFileScanner { -private: - struct DirectoryState - { - utf8 * Directory; - int Handle; - }; + virtual ~IFileScanner() = default; - // Enumeration options - utf8 * _rootPath; - utf8 * _pattern; - bool _recurse; + virtual const file_info * GetFileInfo() const abstract; + virtual const utf8 * GetPath() const abstract; - // Enumeration state - int _fileHandle; - std::stack _directoryStack; - - // Current enumeration - file_info * _fileInfo; - utf8 * _path; - -public: - FileEnumerator(const utf8 * pattern, bool recurse); - ~FileEnumerator(); - - const file_info * GetFileInfo() const { return _fileInfo; } - const utf8 * GetPath() const { return _path; } - - void Reset(); - bool Next(); - -private: - void CloseHandles(); + virtual void Reset() abstract; + virtual bool Next() abstract; }; + +namespace Path +{ + IFileScanner * ScanDirectory(const utf8 * pattern, bool recurse); +} diff --git a/src/object/ObjectRepository.cpp b/src/object/ObjectRepository.cpp index 68ebe6d0c6..9ddc4eecd0 100644 --- a/src/object/ObjectRepository.cpp +++ b/src/object/ObjectRepository.cpp @@ -240,11 +240,11 @@ private: String::Set(pattern, sizeof(pattern), directory); Path::Append(pattern, sizeof(pattern), "*.dat"); - auto fileEnumerator = FileEnumerator(pattern, true); - while (fileEnumerator.Next()) + IFileScanner * scanner = Path::ScanDirectory(pattern, true); + while (scanner->Next()) { - const file_info * enumFileInfo = fileEnumerator.GetFileInfo(); - const utf8 * enumPath = fileEnumerator.GetPath(); + const file_info * enumFileInfo = scanner->GetFileInfo(); + const utf8 * enumPath = scanner->GetPath(); result->TotalFiles++; result->TotalFileSize += enumFileInfo->size; @@ -254,6 +254,7 @@ private: result->FileDateModifiedChecksum = ror32(result->FileDateModifiedChecksum, 5); result->PathChecksum += GetPathChecksum(enumPath); } + delete scanner; } void Construct() @@ -282,12 +283,13 @@ private: String::Set(pattern, sizeof(pattern), directory); Path::Append(pattern, sizeof(pattern), "*.dat"); - auto fileEnumerator = FileEnumerator(pattern, true); - while (fileEnumerator.Next()) + IFileScanner * scanner = Path::ScanDirectory(pattern, true); + while (scanner->Next()) { - const utf8 * enumPath = fileEnumerator.GetPath(); + const utf8 * enumPath = scanner->GetPath(); ScanObject(enumPath); } + delete scanner; } void ScanObject(const utf8 * path) diff --git a/src/ride/TrackDesignRepository.cpp b/src/ride/TrackDesignRepository.cpp index aedf6c37d3..4adb2ca8dc 100644 --- a/src/ride/TrackDesignRepository.cpp +++ b/src/ride/TrackDesignRepository.cpp @@ -202,12 +202,13 @@ private: String::Set(pattern, sizeof(pattern), directory); Path::Append(pattern, sizeof(pattern), "*.td6"); - auto fileEnumerator = FileEnumerator(pattern, true); - while (fileEnumerator.Next()) + IFileScanner * scanner = Path::ScanDirectory(pattern, true); + while (scanner->Next()) { - const utf8 * path = fileEnumerator.GetPath(); + const utf8 * path = scanner->GetPath(); AddTrack(path, flags); } + delete scanner; } void AddTrack(const utf8 * path, uint32 flags = 0)