diff options
-rw-r--r-- | platform/platform.hpp | 16 | ||||
-rw-r--r-- | platform/platform_tests/platform_test.cpp | 79 | ||||
-rw-r--r-- | platform/platform_unix_impl.cpp | 55 | ||||
-rw-r--r-- | std/set.hpp | 1 |
4 files changed, 149 insertions, 2 deletions
diff --git a/platform/platform.hpp b/platform/platform.hpp index 7d916994c6..c54f04e1e9 100644 --- a/platform/platform.hpp +++ b/platform/platform.hpp @@ -24,7 +24,14 @@ public: ERR_OK = 0, ERR_UNKNOWN = 1 }; - + + enum EFileType + { + FILE_TYPE_UNKNOWN = 0x1, + FILE_TYPE_REGULAR = 0x2, + FILE_TYPE_DIRECTORY = 0x4 + }; + protected: /// Usually read-only directory for application resources string m_resourcesDir; @@ -79,6 +86,9 @@ public: /// Creates directory at filesystem EError MkDir(string const & dirName) const; + /// Removes empty directory from the filesystem. + static EError RmDir(string const & dirName); + /// @TODO create join method for string concatenation /// @return path for directory with temporary files with slash at the end @@ -110,6 +120,10 @@ public: static void GetFilesByRegExp(string const & directory, string const & regexp, FilesList & outFiles); //@} + static EError GetFilesByType(string const & directory, unsigned typeMask, FilesList & outFiles); + + static EError GetFileType(string const & path, EFileType & type); + /// @return false if file is not exist /// @note Check files in Writable dir first, and in ReadDir if not exist in Writable dir bool GetFileSizeByName(string const & fileName, uint64_t & size) const; diff --git a/platform/platform_tests/platform_test.cpp b/platform/platform_tests/platform_test.cpp index 4cd82f1cf8..f2d04ff973 100644 --- a/platform/platform_tests/platform_test.cpp +++ b/platform/platform_tests/platform_test.cpp @@ -4,14 +4,35 @@ #include "defines.hpp" +#include "coding/file_name_utils.hpp" #include "coding/file_writer.hpp" #include "coding/internal/file_data.hpp" #include "base/logging.hpp" +#include "base/scope_guard.hpp" +#include "std/bind.hpp" +#include "std/initializer_list.hpp" +#include "std/set.hpp" +namespace +{ char const * TEST_FILE_NAME = "some_temporary_unit_test_file.tmp"; +void CheckFilesPresence(string const & baseDir, unsigned typeMask, + initializer_list<pair<string, size_t>> const & files) +{ + Platform::FilesList filesList; + TEST_EQUAL(Platform::GetFilesByType(baseDir, typeMask, filesList), Platform::ERR_OK, + ("Can't get files from", baseDir)); + multiset<string> filesSet(filesList.begin(), filesList.end()); + for (auto const & file : files) + TEST_EQUAL(filesSet.count(file.first), file.second, (file.first, file.second)); + TEST_EQUAL(0, filesSet.count("."), ()); + TEST_EQUAL(0, filesSet.count(".."), ()); +} +} // namespace + UNIT_TEST(WritableDir) { string const path = GetPlatform().WritableDir() + TEST_FILE_NAME; @@ -83,6 +104,64 @@ UNIT_TEST(GetFilesInDir_Smoke) TEST_EQUAL(files1.size(), 0, ()); } +UNIT_TEST(DirsRoutines) +{ + Platform & platform = GetPlatform(); + string const baseDir = platform.WritableDir(); + string const testDir = my::JoinFoldersToPath(baseDir, "test-dir"); + + TEST(!Platform::IsFileExistsByFullPath(testDir), ()); + TEST_EQUAL(platform.MkDir(testDir), Platform::ERR_OK, ()); + + TEST(Platform::IsFileExistsByFullPath(testDir), ()); + TEST_EQUAL(Platform::RmDir(testDir), Platform::ERR_OK, ()); + + TEST(!Platform::IsFileExistsByFullPath(testDir), ()); +} + +UNIT_TEST(GetFilesByType) +{ + string const kTestDirBaseName = "test-dir"; + string const kTestFileBaseName = "test-file"; + + Platform & platform = GetPlatform(); + string const baseDir = platform.WritableDir(); + + string const testDir = my::JoinFoldersToPath(baseDir, kTestDirBaseName); + TEST_EQUAL(platform.MkDir(testDir), Platform::ERR_OK, ()); + MY_SCOPE_GUARD(removeTestDir, bind(&Platform::RmDir, testDir)); + + string const testFile = my::JoinFoldersToPath(baseDir, kTestFileBaseName); + TEST(!Platform::IsFileExistsByFullPath(testFile), ()); + { + FileWriter writer(testFile); + } + TEST(Platform::IsFileExistsByFullPath(testFile), ()); + MY_SCOPE_GUARD(removeTestFile, bind(FileWriter::DeleteFileX, testFile)); + + CheckFilesPresence(baseDir, Platform::FILE_TYPE_DIRECTORY, + {{ + kTestDirBaseName, 1 /* present */ + }, + { + kTestFileBaseName, 0 /* not present */ + }}); + CheckFilesPresence(baseDir, Platform::FILE_TYPE_REGULAR, + {{ + kTestDirBaseName, 0 /* not present */ + }, + { + kTestFileBaseName, 1 /* present */ + }}); + CheckFilesPresence(baseDir, Platform::FILE_TYPE_DIRECTORY | Platform::FILE_TYPE_REGULAR, + {{ + kTestDirBaseName, 1 /* present */ + }, + { + kTestFileBaseName, 1 /* present */ + }}); +} + UNIT_TEST(GetFileSize) { Platform & pl = GetPlatform(); diff --git a/platform/platform_unix_impl.cpp b/platform/platform_unix_impl.cpp index fbb17cfe0d..9dc5c0c1c5 100644 --- a/platform/platform_unix_impl.cpp +++ b/platform/platform_unix_impl.cpp @@ -1,12 +1,19 @@ #include "platform/platform.hpp" #include "platform/platform_unix_impl.hpp" +#include "coding/file_name_utils.hpp" + #include "base/logging.hpp" #include "base/regexp.hpp" +#include "base/scope_guard.hpp" + +#include "std/algorithm.hpp" +#include "std/bind.hpp" +#include "std/cstring.hpp" #include <dirent.h> #include <sys/stat.h> -#include "std/algorithm.hpp" +#include <unistd.h> #if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) #include <sys/mount.h> @@ -100,12 +107,58 @@ void Platform::GetSystemFontNames(FilesList & res) const #endif } +// static +Platform::EError Platform::GetFilesByType(string const & directory, unsigned typeMask, + FilesList & outFiles) +{ + DIR * dir = opendir(directory.c_str()); + if (!dir) + return ERR_UNKNOWN; + MY_SCOPE_GUARD(closeDirGuard, bind(&closedir, dir)); + while (struct dirent * entry = readdir(dir)) + { + char const * const name = entry->d_name; + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + continue; + + string const path = my::JoinFoldersToPath(directory, name); + + EFileType type; + if (GetFileType(path, type) != ERR_OK) + continue; + if (typeMask & type) + outFiles.push_back(name); + } + return ERR_OK; +} + +// static +Platform::EError Platform::GetFileType(string const & path, EFileType & type) +{ + struct stat stats; + if (stat(path.c_str(), &stats) != 0) + return ERR_UNKNOWN; + if (S_ISREG(stats.st_mode)) + type = FILE_TYPE_REGULAR; + else if (S_ISDIR(stats.st_mode)) + type = FILE_TYPE_DIRECTORY; + else + type = FILE_TYPE_UNKNOWN; + return ERR_OK; +} + bool Platform::IsFileExistsByFullPath(string const & filePath) { struct stat s; return stat(filePath.c_str(), &s) == 0; } +// static +Platform::EError Platform::RmDir(string const & dirName) +{ + return rmdir(dirName.c_str()) == 0 ? ERR_OK : ERR_UNKNOWN; +} + bool Platform::GetFileSizeByFullPath(string const & filePath, uint64_t & size) { struct stat s; diff --git a/std/set.hpp b/std/set.hpp index a1dcd481ac..6bf8320321 100644 --- a/std/set.hpp +++ b/std/set.hpp @@ -11,6 +11,7 @@ #else #include <set> #endif +using std::multiset; using std::set; #ifdef DEBUG_NEW |