| Index: src/DefaultFileSystem.cpp |
| =================================================================== |
| --- a/src/DefaultFileSystem.cpp |
| +++ b/src/DefaultFileSystem.cpp |
| @@ -14,17 +14,19 @@ |
| * You should have received a copy of the GNU General Public License |
| * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| #include <AdblockPlus/DefaultFileSystem.h> |
| #include <cstdio> |
| #include <cstring> |
| #include <fstream> |
| +#include <sstream> |
| #include <stdexcept> |
| +#include <thread> |
| #include <sys/types.h> |
| #ifdef _WIN32 |
| #include <windows.h> |
| #include <Shlobj.h> |
| #include <Shlwapi.h> |
| #else |
| @@ -62,47 +64,48 @@ |
| std::string NormalizePath(const std::string& path) |
| { |
| return path; |
| } |
| #endif |
| } |
| std::shared_ptr<std::istream> |
| -DefaultFileSystem::Read(const std::string& path) const |
| +DefaultFileSystemSync::Read(const std::string& path) const |
| { |
| std::shared_ptr<std::istream> result(new std::ifstream(NormalizePath(path).c_str())); |
| if (result->fail()) |
| throw RuntimeErrorWithErrno("Failed to open " + path); |
| return result; |
| } |
| -void DefaultFileSystem::Write(const std::string& path, |
| - std::istream& data) |
| + |
| +void DefaultFileSystemSync::Write(const std::string& path, |
| + std::istream& data) |
| { |
| std::ofstream file(NormalizePath(path).c_str(), std::ios_base::out | std::ios_base::binary); |
| file << Utils::Slurp(data); |
| } |
| -void DefaultFileSystem::Move(const std::string& fromPath, |
| - const std::string& toPath) |
| +void DefaultFileSystemSync::Move(const std::string& fromPath, |
| + const std::string& toPath) |
| { |
| if (rename(NormalizePath(fromPath).c_str(), NormalizePath(toPath).c_str())) |
| throw RuntimeErrorWithErrno("Failed to move " + fromPath + " to " + toPath); |
| } |
| -void DefaultFileSystem::Remove(const std::string& path) |
| +void DefaultFileSystemSync::Remove(const std::string& path) |
| { |
| if (remove(NormalizePath(path).c_str())) |
| throw RuntimeErrorWithErrno("Failed to remove " + path); |
| } |
| -FileSystem::StatResult DefaultFileSystem::Stat(const std::string& path) const |
| +IFileSystem::StatResult DefaultFileSystemSync::Stat(const std::string& path) const |
| { |
| - FileSystem::StatResult result; |
| + IFileSystem::StatResult result; |
| #ifdef WIN32 |
| WIN32_FILE_ATTRIBUTE_DATA data; |
| if (!GetFileAttributesExW(NormalizePath(path).c_str(), GetFileExInfoStandard, &data)) |
| { |
| DWORD err = GetLastError(); |
| if (err == ERROR_FILE_NOT_FOUND || |
| err == ERROR_PATH_NOT_FOUND || |
| err == ERROR_INVALID_DRIVE) |
| @@ -156,17 +159,17 @@ |
| + static_cast<int64_t>(nativeStat.st_mtim.tv_nsec) / NSEC_IN_MSEC; |
| #else |
| result.lastModified = static_cast<int64_t>(nativeStat.st_mtime) * MSEC_IN_SEC; |
| #endif |
| return result; |
| #endif |
| } |
| -std::string DefaultFileSystem::Resolve(const std::string& path) const |
| +std::string DefaultFileSystemSync::Resolve(const std::string& path) const |
| { |
| if (basePath == "") |
| { |
| return path; |
| } |
| else |
| { |
| #ifdef _WIN32 |
| @@ -179,18 +182,153 @@ |
| } |
| else |
| { |
| return path; |
| } |
| } |
| } |
| -void DefaultFileSystem::SetBasePath(const std::string& path) |
| +void DefaultFileSystemSync::SetBasePath(const std::string& path) |
| { |
| basePath = path; |
| if (*basePath.rbegin() == PATH_SEPARATOR) |
| { |
| basePath.resize(basePath.size() - 1); |
| } |
| } |
| +DefaultFileSystem::DefaultFileSystem(const FileSystemSyncPtr& syncImpl) |
| + : syncImpl(syncImpl) |
| +{ |
| +} |
| + |
| +void DefaultFileSystem::Read(const std::string& path, |
| + const ReadCallback& callback) const |
| +{ |
| + auto impl = syncImpl; |
| + std::thread([impl, path, callback] |
| + { |
| + std::string error; |
| + try |
| + { |
| + auto result = impl->Read(path); |
| + std::stringstream output; |
| + output << result->rdbuf(); |
| + std::string buffer = output.str(); |
| + callback(std::move(buffer), error); |
| + return; |
| + } |
| + catch (std::exception& e) |
| + { |
| + error = e.what(); |
| + } |
| + catch (...) |
| + { |
| + error = "Unknown error while reading from " + path; |
| + } |
| + callback("", error); |
| + }).detach(); |
| +} |
| + |
| +void DefaultFileSystem::Write(const std::string& path, |
| + const std::string& data, |
| + const Callback& callback) |
| +{ |
| + auto impl = syncImpl; |
| + std::thread([impl, path, data, callback] |
| + { |
| + std::string error; |
| + try |
| + { |
| + std::stringstream stream; |
| + stream << data; |
| + impl->Write(path, stream); |
| + } |
| + catch (std::exception& e) |
| + { |
| + error = e.what(); |
| + } |
| + catch (...) |
| + { |
| + error = "Unknown error while writing to " + path; |
| + } |
| + callback(error); |
| + }).detach(); |
| +} |
| + |
| +void DefaultFileSystem::Move(const std::string& fromPath, |
| + const std::string& toPath, |
| + const Callback& callback) |
| +{ |
| + auto impl = syncImpl; |
| + std::thread([impl, fromPath, toPath, callback] |
| + { |
| + std::string error; |
| + try |
| + { |
| + impl->Move(fromPath, toPath); |
| + } |
| + catch (std::exception& e) |
| + { |
| + error = e.what(); |
| + } |
| + catch (...) |
| + { |
| + error = "Unknown error while moving " + fromPath + " to " + toPath; |
| + } |
| + callback(error); |
| + }).detach(); |
| +} |
| + |
| +void DefaultFileSystem::Remove(const std::string& path, |
| + const Callback& callback) |
| +{ |
| + auto impl = syncImpl; |
| + std::thread([impl, path, callback] |
| + { |
| + std::string error; |
| + try |
| + { |
| + impl->Remove(path); |
| + } |
| + catch (std::exception& e) |
| + { |
| + error = e.what(); |
| + } |
| + catch (...) |
| + { |
| + error = "Unknown error while removing " + path; |
| + } |
| + callback(error); |
| + }).detach(); |
| +} |
| + |
| +void DefaultFileSystem::Stat(const std::string& path, |
| + const StatCallback& callback) const |
| +{ |
| + auto impl = syncImpl; |
| + std::thread([impl, path, callback] |
| + { |
| + std::string error; |
| + try |
| + { |
| + auto result = impl->Stat(path); |
| + callback(result, error); |
| + return; |
| + } |
| + catch (std::exception& e) |
| + { |
| + error = e.what(); |
| + } |
| + catch (...) |
| + { |
| + error = "Unknown error while calling stat on " + path; |
| + } |
| + callback(StatResult(), error); |
| + }).detach(); |
| +} |
| + |
| +std::string DefaultFileSystem::Resolve(const std::string& path) const |
| +{ |
| + return syncImpl->Resolve(path); |
| +} |