diff --git a/io/path.cpp b/io/path.cpp index 2570322..92b0192 100644 --- a/io/path.cpp +++ b/io/path.cpp @@ -8,20 +8,21 @@ #include #include #ifdef PLATFORM_UNIX -#include -#include -#include -#include +# include +# include +# include +# include +# include #else -#ifdef PLATFORM_WINDOWS -#ifdef UNICODE -#undef UNICODE -#endif -#ifdef _UNICODE -#undef _UNICODE -#endif -#include -#endif +# ifdef PLATFORM_WINDOWS +# ifdef UNICODE +# undef UNICODE +# endif +# ifdef _UNICODE +# undef _UNICODE +# endif +# include +# endif #endif using namespace std; @@ -37,17 +38,38 @@ string fileName(const string &path) size_t lastSlash = path.rfind('/'); size_t lastBackSlash = path.rfind('\\'); size_t lastSeparator; - if(lastSlash == string::npos && lastBackSlash == string::npos) + if(lastSlash == string::npos && lastBackSlash == string::npos) { return path; - else if(lastSlash == string::npos) + } else if(lastSlash == string::npos) { lastSeparator = lastBackSlash; - else if(lastBackSlash == string::npos) + } else if(lastBackSlash == string::npos) { lastSeparator = lastSlash; - else + } else { lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; + } return path.substr(lastSeparator + 1); } +/*! + * \brief Returns the directory of the specified \a path string (including trailing slash). + */ +string directory(const string &path) +{ + size_t lastSlash = path.rfind('/'); + size_t lastBackSlash = path.rfind('\\'); + size_t lastSeparator; + if(lastSlash == string::npos && lastBackSlash == string::npos) { + return string(); + } else if(lastSlash == string::npos) { + lastSeparator = lastBackSlash; + } else if(lastBackSlash == string::npos) { + lastSeparator = lastSlash; + } else { + lastSeparator = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; + } + return path.substr(0, lastSeparator + 1); +} + /*! * \brief Removes invalid characters from the specified \a fileName. * @@ -158,4 +180,39 @@ bool settingsDirectory(std::string &result, std::string applicationDirectoryName return true; } +/*! + * \brief Returns the names of the directory entries in the specified \a path with the specified \a types. + */ +std::list directoryEntries(const char *path, DirectoryEntryType types) +{ +#ifdef PLATFORM_UNIX + list entries; + if(auto dir = opendir(path)) { + while(auto dirEntry = readdir(dir)) { + bool filter = false; + switch(dirEntry->d_type) { + case DT_REG: + filter = (types & DirectoryEntryType::File) != DirectoryEntryType::None; + break; + case DT_DIR: + filter = (types & DirectoryEntryType::Directory) != DirectoryEntryType::None; + break; + case DT_LNK: + filter = (types & DirectoryEntryType::Symlink) != DirectoryEntryType::None; + break; + default: + filter = (types & DirectoryEntryType::All) != DirectoryEntryType::None; + } + if(filter) { + entries.emplace_back(dirEntry->d_name); + } + } + closedir(dir); + } + return entries; +#else + return list(); // TODO +#endif +} + } diff --git a/io/path.h b/io/path.h index e186696..3c95b49 100644 --- a/io/path.h +++ b/io/path.h @@ -7,6 +7,7 @@ #include "../application/global.h" #include +#include #ifdef PLATFORM_WINDOWS # define PATH_SEP_CHAR '\\' @@ -22,9 +23,33 @@ namespace IoUtilities { +/*! + * \brief The DirectoryEntryType enum specifies the type of a directory entry (file, directory or symlink). + */ +enum class DirectoryEntryType : unsigned char +{ + None = 0, + File = 1, + Directory = 2, + Symlink = 4, + All = 0xFF +}; + +constexpr DirectoryEntryType operator|(DirectoryEntryType lhs, DirectoryEntryType rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +constexpr DirectoryEntryType operator&(DirectoryEntryType lhs, DirectoryEntryType rhs) +{ + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + LIB_EXPORT std::string fileName(const std::string &path); +LIB_EXPORT std::string directory(const std::string &path); LIB_EXPORT void removeInvalidChars(std::string &fileName); LIB_EXPORT bool settingsDirectory(std::string &result, std::string applicationDirectoryName = std::string(), bool createApplicationDirectory = false); +LIB_EXPORT std::list directoryEntries(const char *path, DirectoryEntryType types = DirectoryEntryType::All); } diff --git a/tests/iotests.cpp b/tests/iotests.cpp index 0ae240b..9be71f7 100644 --- a/tests/iotests.cpp +++ b/tests/iotests.cpp @@ -13,6 +13,7 @@ #include #include +#include using namespace std; using namespace IoUtilities; @@ -224,9 +225,27 @@ void IoTests::testBitReader() void IoTests::testPathUtilities() { CPPUNIT_ASSERT(fileName("/usr/lib/libc++utilities.so") == "libc++utilities.so"); + CPPUNIT_ASSERT(directory("/usr/lib/libc++utilities.so") == "/usr/lib/"); + CPPUNIT_ASSERT(directory("libc++utilities.so").empty()); string invalidPath("lib/c++uti*lities.so?"); removeInvalidChars(invalidPath); CPPUNIT_ASSERT(invalidPath == "libc++utilities.so"); +#ifdef PLATFORM_UNIX + const string iniFilePath = TestUtilities::testFilePath("test.ini"); + const string testFilesDir = iniFilePath.substr(0, iniFilePath.size() - 9); + auto testFilesDirEntries = directoryEntries(testFilesDir.c_str(), DirectoryEntryType::All); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "test.ini") != testFilesDirEntries.cend()); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), ".") != testFilesDirEntries.cend()); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "..") != testFilesDirEntries.cend()); + testFilesDirEntries = directoryEntries(testFilesDir.c_str(), DirectoryEntryType::Directory); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "test.ini") == testFilesDirEntries.cend()); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), ".") != testFilesDirEntries.cend()); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "..") != testFilesDirEntries.cend()); + testFilesDirEntries = directoryEntries(testFilesDir.c_str(), DirectoryEntryType::File); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "test.ini") != testFilesDirEntries.cend()); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), ".") == testFilesDirEntries.cend()); + CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "..") == testFilesDirEntries.cend()); +#endif } /*!