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())); |
+ std::shared_ptr<std::istream> result(new std::ifstream(NormalizePath(path).c_str(), std::ios_base::binary)); |
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::ostream& data) |
{ |
std::ofstream file(NormalizePath(path).c_str(), std::ios_base::out | std::ios_base::binary); |
- file << Utils::Slurp(data); |
+ file << data.rdbuf(); |
} |
-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,156 @@ |
} |
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 is = impl->Read(path); |
+ is->seekg(0, std::ios_base::end); |
+ auto dataSize = is->tellg(); |
+ is->seekg(0, std::ios_base::beg); |
+ |
+ std::vector<char> data(dataSize); |
+ is->read(data.data(), data.size()); |
+ callback(std::move(data), error); |
+ return; |
+ } |
+ catch (std::exception& e) |
+ { |
+ error = e.what(); |
+ } |
+ catch (...) |
+ { |
+ error = "Unknown error while reading from " + path; |
+ } |
+ callback(std::vector<char>(), error); |
+ }).detach(); |
+} |
+ |
+void DefaultFileSystem::Write(const std::string& path, |
+ const std::vector<char>& data, |
+ const Callback& callback) |
+{ |
+ auto impl = syncImpl; |
+ std::thread([impl, path, data, callback] |
+ { |
+ std::string error; |
+ try |
+ { |
+ std::stringstream stream; |
+ stream.write(data.data(), data.size()); |
+ 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); |
+} |