diff --git a/openVulkanoCpp/Host/WebResourceLoader.cpp b/openVulkanoCpp/Host/WebResourceLoader.cpp new file mode 100644 index 0000000..e3bb245 --- /dev/null +++ b/openVulkanoCpp/Host/WebResourceLoader.cpp @@ -0,0 +1,90 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "WebResourceLoader.hpp" +#include "IO/AppFolders.hpp" +#include "Base/Utils.hpp" + +#include +#include +#include + +namespace OpenVulkano +{ + namespace + { + size_t curlDownloader(void* contents, size_t size, size_t memBlockCount, void* userData) + { + size_t totalSize = size * memBlockCount; + std::vector* buffer = static_cast*>(userData); + buffer->insert(buffer->end(), static_cast(contents), static_cast(contents) + totalSize); + return totalSize; + } + } + + WebResourceLoader::WebResourceLoader() + { + m_cacheDirectory = AppFolders::GetAppCacheDir() / "resources"; + std::filesystem::create_directories(m_cacheDirectory); + curl_global_init(CURL_GLOBAL_DEFAULT); + } + + WebResourceLoader::~WebResourceLoader() { curl_global_cleanup(); } + + std::filesystem::path WebResourceLoader::GetCacheFilePath(const std::string& url) + { + size_t hash = std::hash {}(url); + std::string hashedUrl = std::to_string(hash); + + return m_cacheDirectory / hashedUrl; + } + + Array WebResourceLoader::DownloadResource(const std::string& url) + { + std::vector buffer; + + CURL* curl = curl_easy_init(); + if (curl) + { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curlDownloader); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); + +#ifdef __APPLE__ + curl_easy_setopt(curl, CURLOPT_SSLENGINE, "DarwinSSL"); +#endif + + CURLcode result = curl_easy_perform(curl); + if (result != CURLE_OK) + { + curl_easy_cleanup(curl); + throw std::runtime_error("Failed to download resource: '" + url + "' - " + curl_easy_strerror(result)); + } + curl_easy_cleanup(curl); + } + + std::filesystem::path cacheFilePath = GetCacheFilePath(url); + std::ofstream file(cacheFilePath, std::ios::binary); + file.write(buffer.data(), buffer.size()); + return Array(buffer); + } + + bool WebResourceLoader::IsUrl(const std::string& str) + { + return str.find("http://") == 0 || str.find("https://") == 0 || str.find("ftp://") == 0; + } + + Array WebResourceLoader::GetResource(const std::string& resourceName) + { + if (IsUrl(resourceName)) + { + std::filesystem::path cacheFilePath = GetCacheFilePath(resourceName); + if (std::filesystem::exists(cacheFilePath)) { return Utils::ReadFile(cacheFilePath.string()); } + else { return DownloadResource(resourceName); } + } + throw std::runtime_error("Resource name is not a valid URL"); + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/WebResourceLoader.hpp b/openVulkanoCpp/Host/WebResourceLoader.hpp new file mode 100644 index 0000000..3a267b3 --- /dev/null +++ b/openVulkanoCpp/Host/WebResourceLoader.hpp @@ -0,0 +1,28 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include "ResourceLoader.hpp" + +#include +#include + +namespace OpenVulkano +{ + class WebResourceLoader : public ResourceLoader + { + std::filesystem::path m_cacheDirectory; + + std::filesystem::path GetCacheFilePath(const std::string& url); + Array DownloadResource(const std::string& url); + bool IsUrl(const std::string& str); + + public: + WebResourceLoader(); + ~WebResourceLoader(); + Array GetResource(const std::string& resourceName) override; + }; +} \ No newline at end of file