diff --git a/src/core/FileStream.hpp b/src/core/FileStream.hpp index f632199f7f..1b3dfd56e2 100644 --- a/src/core/FileStream.hpp +++ b/src/core/FileStream.hpp @@ -40,6 +40,11 @@ private: uint64 _fileSize; public: + FileStream(const std::string &path, int fileMode) : + FileStream(path.c_str(), fileMode) + { + } + FileStream(const utf8 * path, int fileMode) { const char * mode; diff --git a/src/object/ObjectRepository.cpp b/src/object/ObjectRepository.cpp index 9033a9c700..1e10c1915a 100644 --- a/src/object/ObjectRepository.cpp +++ b/src/object/ObjectRepository.cpp @@ -30,6 +30,7 @@ #include "../core/Path.hpp" #include "../core/Stopwatch.hpp" #include "../core/String.hpp" +#include "../PlatformEnvironment.h" #include "../ScenarioRepository.h" #include "Object.h" #include "ObjectFactory.h" @@ -93,12 +94,18 @@ static void ReportMissingObject(const rct_object_entry * entry); class ObjectRepository : public IObjectRepository { + IPlatformEnvironment * _env; std::vector _items; QueryDirectoryResult _queryDirectoryResult; ObjectEntryMap _itemMap; uint16 _languageId; public: + ObjectRepository(IPlatformEnvironment * env) + { + _env = env; + } + ~ObjectRepository() { ClearItems(); @@ -110,11 +117,10 @@ public: _queryDirectoryResult = { 0 }; - utf8 path[MAX_PATH]; - GetRCT2ObjectPath(path, sizeof(path)); - QueryDirectory(&_queryDirectoryResult, path); - GetUserObjectPath(path, sizeof(path)); - QueryDirectory(&_queryDirectoryResult, path); + const std::string &rct2Path = _env->GetDirectoryPath(DIRBASE_RCT2, DIRID_OBJECT); + const std::string &openrct2Path = _env->GetDirectoryPath(DIRBASE_OPENRCT2, DIRID_OBJECT); + QueryDirectory(&_queryDirectoryResult, rct2Path); + QueryDirectory(&_queryDirectoryResult, openrct2Path); if (!Load()) { @@ -227,10 +233,10 @@ private: _itemMap.clear(); } - void QueryDirectory(QueryDirectoryResult * result, const utf8 * directory) + void QueryDirectory(QueryDirectoryResult * result, const std::string &directory) { utf8 pattern[MAX_PATH]; - String::Set(pattern, sizeof(pattern), directory); + String::Set(pattern, sizeof(pattern), directory.c_str()); Path::Append(pattern, sizeof(pattern), "*.dat"); Path::QueryDirectory(result, pattern); } @@ -245,20 +251,19 @@ private: auto stopwatch = Stopwatch(); stopwatch.Start(); - utf8 path[MAX_PATH]; - GetRCT2ObjectPath(path, sizeof(path)); - ScanDirectory(path); - GetUserObjectPath(path, sizeof(path)); - ScanDirectory(path); + const std::string &rct2Path = _env->GetDirectoryPath(DIRBASE_RCT2, DIRID_OBJECT); + const std::string &openrct2Path = _env->GetDirectoryPath(DIRBASE_OPENRCT2, DIRID_OBJECT); + ScanDirectory(rct2Path); + ScanDirectory(openrct2Path); stopwatch.Stop(); Console::WriteLine("Scanning complete in %.2f seconds.", stopwatch.GetElapsedMilliseconds() / 1000.0f); } - void ScanDirectory(const utf8 * directory) + void ScanDirectory(const std::string &directory) { utf8 pattern[MAX_PATH]; - String::Set(pattern, sizeof(pattern), directory); + String::Set(pattern, sizeof(pattern), directory.c_str()); Path::Append(pattern, sizeof(pattern), "*.dat"); IFileScanner * scanner = Path::ScanDirectory(pattern, true); @@ -288,9 +293,7 @@ private: bool Load() { - utf8 path[MAX_PATH]; - GetRepositoryPath(path, sizeof(path)); - + const std::string &path = _env->GetFilePath(PATHID_CACHE_OBJECTS); try { auto fs = FileStream(path, FILE_MODE_OPEN); @@ -329,9 +332,7 @@ private: void Save() const { - utf8 path[MAX_PATH]; - GetRepositoryPath(path, sizeof(path)); - + const std::string &path = _env->GetFilePath(PATHID_CACHE_OBJECTS); try { auto fs = FileStream(path, FILE_MODE_WRITE); @@ -355,7 +356,7 @@ private: } catch (IOException ex) { - log_error("Unable to write object repository index."); + log_error("Unable to write object repository index to '%s'.", path.c_str()); } } @@ -578,7 +579,7 @@ private: return salt; } - static void GetPathForNewObject(utf8 * buffer, size_t bufferSize, const char * name) + void GetPathForNewObject(utf8 * buffer, size_t bufferSize, const char * name) { char normalisedName[9] = { 0 }; for (int i = 0; i < 8; i++) @@ -593,7 +594,8 @@ private: } } - GetUserObjectPath(buffer, bufferSize); + const std::string &userObjPath = _env->GetDirectoryPath(DIRBASE_USER, DIRID_OBJECT); + String::Set(buffer, bufferSize, userObjPath.c_str()); platform_ensure_directory_exists(buffer); Path::Append(buffer, bufferSize, normalisedName); @@ -606,37 +608,31 @@ private: snprintf(counterString, sizeof(counterString), "-%02X", counter); counter++; - GetUserObjectPath(buffer, bufferSize); + String::Set(buffer, bufferSize, userObjPath.c_str()); Path::Append(buffer, bufferSize, normalisedName); String::Append(buffer, bufferSize, counterString); String::Append(buffer, bufferSize, ".DAT"); } } - - static void GetRepositoryPath(utf8 * buffer, size_t bufferSize) - { - platform_get_user_directory(buffer, nullptr, bufferSize); - safe_strcat_path(buffer, "objects.idx", bufferSize); - } - - static void GetRCT2ObjectPath(utf8 * buffer, size_t bufferSize) - { - Path::GetDirectory(buffer, bufferSize, gRCT2AddressObjectDataPath); - } - - static void GetUserObjectPath(utf8 * buffer, size_t bufferSize) - { - platform_get_user_directory(buffer, "object", bufferSize); - } }; static std::unique_ptr _objectRepository; +IObjectRepository * CreateObjectRepository(IPlatformEnvironment * env) +{ + _objectRepository = std::unique_ptr(new ObjectRepository(env)); + return _objectRepository.get(); +} + IObjectRepository * GetObjectRepository() { if (_objectRepository == nullptr) { - _objectRepository = std::unique_ptr(new ObjectRepository()); + // TODO There should only be one platform environment which needs to be global. + // However it should be not be used here. Instead the object repository should be + // constructed in some initialisation method where it passes this dependency. + IPlatformEnvironment * env = CreatePlatformEnvironment(); + CreateObjectRepository(env); } return _objectRepository.get(); } diff --git a/src/object/ObjectRepository.h b/src/object/ObjectRepository.h index e369960daf..11ef872873 100644 --- a/src/object/ObjectRepository.h +++ b/src/object/ObjectRepository.h @@ -28,7 +28,8 @@ extern "C" #endif #ifdef __cplusplus - class Object; + interface IPlatformEnvironment; + class Object; #else typedef struct Object Object; #endif @@ -77,6 +78,7 @@ interface IObjectRepository size_t dataSize) abstract; }; +IObjectRepository * CreateObjectRepository(IPlatformEnvironment * env); IObjectRepository * GetObjectRepository(); #endif