diff --git a/src/openrct2/core/FileScanner.cpp b/src/openrct2/core/FileScanner.cpp index 886c59df4f..6969ba039f 100644 --- a/src/openrct2/core/FileScanner.cpp +++ b/src/openrct2/core/FileScanner.cpp @@ -377,7 +377,7 @@ private: IFileScanner * Path::ScanDirectory(const std::string &pattern, bool recurse) { - return Path::ScanDirectory(pattern.c_str(), recurse); + return ScanDirectory(pattern.c_str(), recurse); } IFileScanner * Path::ScanDirectory(const utf8 * pattern, bool recurse) @@ -389,6 +389,11 @@ IFileScanner * Path::ScanDirectory(const utf8 * pattern, bool recurse) #endif } +void Path::QueryDirectory(QueryDirectoryResult * result, const std::string &pattern) +{ + return QueryDirectory(result, pattern.c_str()); +} + void Path::QueryDirectory(QueryDirectoryResult * result, const utf8 * pattern) { IFileScanner * scanner = Path::ScanDirectory(pattern, true); diff --git a/src/openrct2/core/FileScanner.h b/src/openrct2/core/FileScanner.h index df4f0ce1a9..4ee88bf800 100644 --- a/src/openrct2/core/FileScanner.h +++ b/src/openrct2/core/FileScanner.h @@ -65,6 +65,14 @@ namespace Path */ IFileScanner * ScanDirectory(const utf8 * pattern, bool recurse); + /** + * Scans a directory and all sub directories + * @param result The query result to modify. + * @param pattern The path followed by a semi-colon delimited list of wildcard patterns. + * @returns An aggregated result of all scanned files. + */ + void QueryDirectory(QueryDirectoryResult * result, const std::string &pattern); + /** * Scans a directory and all sub directories * @param result The query result to modify. diff --git a/src/openrct2/core/Path.cpp b/src/openrct2/core/Path.cpp index c9d0d5dcbf..0b3f9f5c96 100644 --- a/src/openrct2/core/Path.cpp +++ b/src/openrct2/core/Path.cpp @@ -29,7 +29,12 @@ extern "C" namespace Path { - std::string Append(const std::string &a, const std::string &b) + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src) + { + return safe_strcat_path(buffer, src, bufferSize); + } + + std::string Combine(const std::string &a, const std::string &b) { utf8 buffer[MAX_PATH]; String::Set(buffer, sizeof(buffer), a.c_str()); @@ -37,9 +42,9 @@ namespace Path return std::string(buffer); } - utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src) + std::string GetDirectory(const std::string &path) { - return safe_strcat_path(buffer, src, bufferSize); + return GetDirectory(path.c_str()); } utf8 * GetDirectory(const utf8 * path) @@ -66,6 +71,11 @@ namespace Path return buffer; } + std::string GetFileName(const std::string &path) + { + return GetFileName(path.c_str()); + } + const utf8 * GetFileName(const utf8 * path) { const utf8 * lastPathSeperator = nullptr; @@ -132,6 +142,11 @@ namespace Path return buffer; } + const std::string GetExtension(const std::string &path) + { + return GetExtension(path.c_str()); + } + const utf8 * GetExtension(const utf8 * path) { const utf8 * lastDot = nullptr; @@ -187,6 +202,11 @@ namespace Path #endif } + bool Equals(const std::string &a, const std::string &b) + { + return String::Equals(a.c_str(), b.c_str()); + } + bool Equals(const utf8 * a, const utf8 * b) { bool ignoreCase = false; diff --git a/src/openrct2/core/Path.hpp b/src/openrct2/core/Path.hpp index fd0fd59c50..b2abb9ec73 100644 --- a/src/openrct2/core/Path.hpp +++ b/src/openrct2/core/Path.hpp @@ -16,22 +16,24 @@ #pragma once -extern "C" -{ - #include "../common.h" -} +#include +#include "../common.h" namespace Path { - std::string Append(const std::string &a, const std::string &b); utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); + std::string Combine(const std::string &a, const std::string &b); + std::string GetDirectory(const std::string &path); utf8 * GetDirectory(const utf8 * path); utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path); + std::string GetFileName(const std::string &path); const utf8 * GetFileName(const utf8 * path); std::string GetFileNameWithoutExtension(const std::string &path); utf8 * GetFileNameWithoutExtension(const utf8 * path); utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path); + const std::string GetExtension(const std::string &path); const utf8 * GetExtension(const utf8 * path); utf8 * GetAbsolute(utf8 * buffer, size_t bufferSize, const utf8 * relativePath); + bool Equals(const std::string &a, const std::string &b); bool Equals(const utf8 * a, const utf8 * b); } diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index 29045d373c..748207e281 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -50,12 +50,12 @@ namespace String return str == nullptr || str[0] == '\0'; } - sint32 Compare(const std::string &a, const std::string &b, bool ignoreCase = false) + sint32 Compare(const std::string &a, const std::string &b, bool ignoreCase) { return Compare(a.c_str(), b.c_str(), ignoreCase); } - sint32 Compare(const utf8 * a, const utf8 * b, bool ignoreCase = false) + sint32 Compare(const utf8 * a, const utf8 * b, bool ignoreCase) { if (a == b) return true; if (a == nullptr || b == nullptr) return false; @@ -70,6 +70,11 @@ namespace String } } + bool Equals(const std::string &a, const std::string &b, bool ignoreCase) + { + return Equals(a.c_str(), b.c_str(), ignoreCase); + } + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase) { if (a == b) return true; diff --git a/src/openrct2/core/String.hpp b/src/openrct2/core/String.hpp index ad049a8b03..3e01b69fbe 100644 --- a/src/openrct2/core/String.hpp +++ b/src/openrct2/core/String.hpp @@ -29,6 +29,7 @@ namespace String bool IsNullOrEmpty(const utf8 * str); sint32 Compare(const std::string &a, const std::string &b, bool ignoreCase = false); sint32 Compare(const utf8 * a, const utf8 * b, bool ignoreCase = false); + bool Equals(const std::string &a, const std::string &b, bool ignoreCase = false); bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false); bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase = false); size_t LastIndexOf(const utf8 * str, utf8 match); diff --git a/src/openrct2/ride/TrackDesignRepository.cpp b/src/openrct2/ride/TrackDesignRepository.cpp index 3bd7c7177d..215352445e 100644 --- a/src/openrct2/ride/TrackDesignRepository.cpp +++ b/src/openrct2/ride/TrackDesignRepository.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "../core/Collections.hpp" #include "../core/Console.hpp" #include "../core/File.h" #include "../core/FileScanner.h" @@ -65,6 +66,8 @@ enum TRACK_REPO_ITEM_FLAGS class TrackDesignRepository : public ITrackDesignRepository { private: + static constexpr const utf8 * TD_FILE_PATTERN = "*.td4;*.td6"; + IPlatformEnvironment * _env; std::vector _items; @@ -87,13 +90,13 @@ public: return _items.size(); } - size_t GetCountForObjectEntry(uint8 rideType, const utf8 * entry) const override + size_t GetCountForObjectEntry(uint8 rideType, const std::string &entry) const override { size_t count = 0; for (const auto item : _items) { if (item.RideType == rideType && - (entry == nullptr || String::Equals(item.ObjectEntry.c_str(), entry, true))) + (entry.empty() || String::Equals(item.ObjectEntry, entry, true))) { count++; } @@ -101,13 +104,13 @@ public: return count; } - size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry) const override + size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs, uint8 rideType, const std::string &entry) const override { std::vector refs; for (const auto item : _items) { if (item.RideType == rideType && - (entry == nullptr || String::Equals(item.ObjectEntry.c_str(), entry, true))) + (entry.empty() || String::Equals(item.ObjectEntry, entry, true))) { track_design_file_ref ref; ref.name = String::Duplicate(GetNameFromTrackPath(item.Path)); @@ -116,11 +119,7 @@ public: } } - *outRefs = nullptr; - if (refs.size() != 0) - { - *outRefs = Memory::DuplicateArray(refs.data(), refs.size()); - } + *outRefs = Collections::ToArray(refs); return refs.size(); } @@ -143,7 +142,7 @@ public: } } - bool Delete(const utf8 * path) override + bool Delete(const std::string &path) override { bool result = false; size_t index = GetTrackIndex(path); @@ -152,7 +151,7 @@ public: const TrackRepositoryItem * item = &_items[index]; if (!(item->Flags & TRIF_READ_ONLY)) { - if (File::Delete(path)) + if (File::Delete(path.c_str())) { _items.erase(_items.begin() + index); result = true; @@ -162,57 +161,41 @@ public: return result; } - const utf8 * Rename(const utf8 * path, const utf8 * newName) override + std::string Rename(const std::string &path, const std::string &newName) override { - const utf8 * result = nullptr; + std::string result; size_t index = GetTrackIndex(path); if (index != SIZE_MAX) { TrackRepositoryItem * item = &_items[index]; if (!(item->Flags & TRIF_READ_ONLY)) { - utf8 newPath[MAX_PATH]; - Path::GetDirectory(newPath, sizeof(newPath), path); - Path::Append(newPath, sizeof(newPath), newName); - String::Append(newPath, sizeof(newPath), Path::GetExtension(path)); - - if (File::Move(path, newPath)) + std::string directory = Path::GetDirectory(path); + std::string newPath = Path::Combine(directory, newName + Path::GetExtension(path)); + if (File::Move(path.c_str(), newPath.c_str())) { - item->Name = std::string(newName); - item->Path = std::string(newPath); + item->Name = newName; + item->Path = newPath; SortItems(); - - item = GetTrackItem(newPath); - if (item != nullptr) - { - result = item->Path.c_str(); - } + result = newPath; } } } return result; } - const utf8 * Install(const utf8 * path) override + std::string Install(const std::string &path) override { - const utf8 * result = nullptr; - const utf8 * fileName = Path::GetFileName(path); + std::string result; + std::string fileName = Path::GetFileName(path); std::string installDir = _env->GetDirectoryPath(DIRBASE::USER, DIRID::TRACK); - utf8 newPath[MAX_PATH]; - String::Set(newPath, sizeof(newPath), installDir.c_str()); - Path::Append(newPath, sizeof(newPath), fileName); - - if (File::Copy(path, newPath, false)) + std::string newPath = Path::Combine(installDir, fileName); + if (File::Copy(path.c_str(), newPath.c_str(), false)) { AddTrack(path); SortItems(); - - const TrackRepositoryItem * item = GetTrackItem(path); - if (item != nullptr) - { - result = item->Path.c_str(); - } + result = path; } return result; } @@ -220,15 +203,13 @@ public: private: void Query(const std::string &directory) { - utf8 pattern[MAX_PATH]; - String::Set(pattern, sizeof(pattern), directory.c_str()); - Path::Append(pattern, sizeof(pattern), "*.td4;*.td6"); + std::string pattern = Path::Combine(directory, TD_FILE_PATTERN); Path::QueryDirectory(&_directoryQueryResult, pattern); } void Scan(const std::string &directory, uint32 flags = 0) { - std::string pattern = Path::Append(directory, "*.td4;*.td6"); + std::string pattern = Path::Combine(directory, TD_FILE_PATTERN); IFileScanner * scanner = Path::ScanDirectory(pattern, true); while (scanner->Next()) { @@ -339,11 +320,11 @@ private: } } - size_t GetTrackIndex(const utf8 * path) const + size_t GetTrackIndex(const std::string &path) const { for (size_t i = 0; i < _items.size(); i++) { - if (Path::Equals(_items[i].Path.c_str(), path)) + if (Path::Equals(_items[i].Path, path)) { return i; } @@ -351,7 +332,7 @@ private: return SIZE_MAX; } - TrackRepositoryItem * GetTrackItem(const utf8 * path) + TrackRepositoryItem * GetTrackItem(const std::string &path) { TrackRepositoryItem * result = nullptr; size_t index = GetTrackIndex(path); @@ -408,16 +389,18 @@ extern "C" return repo->Delete(path); } - const utf8 * track_repository_rename(const utf8 * path, const utf8 * newName) + bool track_repository_rename(const utf8 * path, const utf8 * newName) { ITrackDesignRepository * repo = GetTrackDesignRepository(); - return repo->Rename(path, newName); + std::string newPath = repo->Rename(path, newName); + return !newPath.empty(); } - const utf8 * track_repository_install(const utf8 * srcPath) + bool track_repository_install(const utf8 * srcPath) { ITrackDesignRepository * repo = GetTrackDesignRepository(); - return repo->Install(srcPath); + std::string newPath = repo->Install(srcPath); + return !newPath.empty(); } utf8 * track_repository_get_name_from_path(const utf8 * path) diff --git a/src/openrct2/ride/TrackDesignRepository.h b/src/openrct2/ride/TrackDesignRepository.h index bcf6ecaa7e..b5d7548d02 100644 --- a/src/openrct2/ride/TrackDesignRepository.h +++ b/src/openrct2/ride/TrackDesignRepository.h @@ -26,6 +26,8 @@ typedef struct track_design_file_ref #ifdef __cplusplus +#include + interface IPlatformEnvironment; interface ITrackDesignRepository @@ -33,15 +35,15 @@ interface ITrackDesignRepository virtual ~ITrackDesignRepository() = default; virtual size_t GetCount() const abstract; - virtual size_t GetCountForObjectEntry(uint8 rideType, const utf8 * entry) const abstract; + virtual size_t GetCountForObjectEntry(uint8 rideType, const std::string &entry) const abstract; virtual size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs, uint8 rideType, - const utf8 * entry) const abstract; + const std::string &entry) const abstract; virtual void Scan() abstract; - virtual bool Delete(const utf8 * path) abstract; - virtual const utf8 * Rename(const utf8 * path, const utf8 * newName) abstract; - virtual const utf8 * Install(const utf8 * path) abstract; + virtual bool Delete(const std::string &path) abstract; + virtual std::string Rename(const std::string &path, const std::string &newName) abstract; + virtual std::string Install(const std::string &path) abstract; }; ITrackDesignRepository * CreateTrackDesignRepository(IPlatformEnvironment * env); @@ -53,13 +55,13 @@ ITrackDesignRepository * GetTrackDesignRepository(); extern "C" { #endif - void track_repository_scan(); - size_t track_repository_get_count_for_ride(uint8 rideType, const utf8 * entry); - size_t track_repository_get_items_for_ride(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry); - utf8 * track_repository_get_name_from_path(const utf8 *path); - bool track_repository_delete(const utf8 *path); - const utf8 * track_repository_rename(const utf8 *path, const utf8 *newName); - const utf8 * track_repository_install(const utf8 *srcPath); + void track_repository_scan(); + size_t track_repository_get_count_for_ride(uint8 rideType, const utf8 * entry); + size_t track_repository_get_items_for_ride(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry); + utf8 * track_repository_get_name_from_path(const utf8 *path); + bool track_repository_delete(const utf8 *path); + bool track_repository_rename(const utf8 *path, const utf8 *newName); + bool track_repository_install(const utf8 *srcPath); #ifdef __cplusplus } #endif