diff --git a/aegisub/libaegisub/include/libaegisub/util.h b/aegisub/libaegisub/include/libaegisub/util.h index 6cbf47e31..d59020d32 100644 --- a/aegisub/libaegisub/include/libaegisub/util.h +++ b/aegisub/libaegisub/include/libaegisub/util.h @@ -31,36 +31,41 @@ namespace agi { TypeDir ///< Directory }; - // Calculate midpoint from a list of Integers + /// Clamp `b` to the range [`a`,`c`] template inline T mid(T a, T b, T c) { return std::max(a, std::min(b, c)); } - // Get the parent directory of a path. - // @param path Path to process. + /// Get the parent directory of a path. + /// @param path Path to process. const std::string DirName(const std::string& path); - // Rename a file. - // @param from Source. - // @param to Destination. + /// Rename a file. + /// @param from Source. + /// @param to Destination. void Rename(const std::string& from, const std::string& to); - // Get time sutable for logging mechinisms. - // @param tv timeval + /// Delete a file + /// @param path Path to file to delete + /// @throws agi::FileNotAccessibleError if file exists but could not be deleted + void Remove(std::string const& path); + + /// Get time suitable for logging mechanisms. + /// @param tv timeval void time_log(agi_timeval &tv); - // Make all alphabetic characters lowercase. - // @param str Input string + /// Make all alphabetic characters lowercase. + /// @param str Input string void str_lower(std::string &str); - // Convert a string to Integer. - // @param str Input string + /// Convert a string to Integer. + /// @param str Input string int strtoi(std::string const& str); bool try_parse(std::string const& str, double *out); bool try_parse(std::string const& str, int *out); /// Check for amount of free space on a Path. - // @param path[in] Path to check - // @param type PathType (default is TypeDir) + /// @param path[in] Path to check + /// @param type PathType (default is TypeDir) uint64_t freespace(std::string const& path, PathType type=TypeDir); struct delete_ptr { diff --git a/aegisub/libaegisub/unix/util.cpp b/aegisub/libaegisub/unix/util.cpp index 230561627..ea556ec6e 100644 --- a/aegisub/libaegisub/unix/util.cpp +++ b/aegisub/libaegisub/unix/util.cpp @@ -60,6 +60,11 @@ void Rename(const std::string& from, const std::string& to) { rename(from.c_str(), to.c_str()); } +void Remove(std::string const& path) { + if (!remove(path.c_str()) && errno != ENOENT) + throw agi::FileNotAccessibleError("Can not remove file: " + path); +} + void time_log(timeval &tv) { gettimeofday(&tv, (struct timezone *)NULL); } diff --git a/aegisub/libaegisub/windows/util_win.cpp b/aegisub/libaegisub/windows/util_win.cpp index 2f55b2e53..995089546 100644 --- a/aegisub/libaegisub/windows/util_win.cpp +++ b/aegisub/libaegisub/windows/util_win.cpp @@ -57,6 +57,14 @@ void Rename(const std::string& from, const std::string& to) { throw agi::FileNotAccessibleError("Can not overwrite file: " + ErrorString(GetLastError())); } +void Remove(std::string const& path) { + if (!DeleteFile(ConvertW(path).c_str())) { + DWORD err = GetLastError(); + if (err != ERROR_FILE_NOT_FOUND) + throw agi::FileNotAccessibleError("Can not remove file: " + ErrorString(err)); + } +} + std::string ErrorString(DWORD error) { LPWSTR lpstr = nullptr; diff --git a/aegisub/tests/libaegisub_util.cpp b/aegisub/tests/libaegisub_util.cpp index 0dad93dbb..0dcb08c5e 100644 --- a/aegisub/tests/libaegisub_util.cpp +++ b/aegisub/tests/libaegisub_util.cpp @@ -62,6 +62,21 @@ TEST(lagi_util, UtilRenameExNotFound) { EXPECT_THROW(util::Rename("./data/nonexistent", ""), FileNotFoundError); } +TEST(lagi_util, RemoveExisting) { + std::ofstream("./data/file_to_remove"); + EXPECT_NO_THROW(util::Remove("./data/file_to_remove")); + std::ifstream check("./data/file_to_remove"); + EXPECT_FALSE(check.good()); +} + +TEST(lagi_util, RemoveNonExisting) { + EXPECT_NO_THROW(util::Remove("./data/nonexistent")); +} + +TEST(lagi_util, RemoveReadOnly) { + EXPECT_THROW(util::Remove("./data/file_read_only"), FileNotAccessibleError); +} + TEST(lagi_util, Utilstr_lower) { std::string str("-!ABCDEFGHIJKLMNOPQRSTUVWXYZ123"); util::str_lower(str);