Add listdir to fileop

This commit is contained in:
2021-12-31 14:10:26 +08:00
parent 027f22abd3
commit 65b9f06319
4 changed files with 109 additions and 0 deletions

View File

@@ -12,12 +12,14 @@
#include <direct.h> #include <direct.h>
#include <fileapi.h> #include <fileapi.h>
#else #else
#include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#endif #endif
#include <fcntl.h> #include <fcntl.h>
#include <ctype.h> #include <ctype.h>
#include "err.h" #include "err.h"
#include "str_util.h"
#include "wchar_util.h" #include "wchar_util.h"
#include "time_util.h" #include "time_util.h"
#include <regex> #include <regex>
@@ -85,6 +87,29 @@ HANDLE get_file_size_internal(wchar_t* fn) {
return CreateFileW(fn, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); return CreateFileW(fn, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
} }
bool listdir_internal(wchar_t* fn, std::list<std::string>& list, bool ignore_hidden_file) {
std::list<std::string> li;
WIN32_FIND_DATAW data;
HANDLE re = FindFirstFileW(fn, &data);
if (re == INVALID_HANDLE_VALUE) return false;
std::string tfn;
do {
if (!wchar_util::wstr_to_str(tfn, data.cFileName, CP_UTF8)) {
FindClose(re);
return false;
}
if ((ignore_hidden_file && tfn.find(".") != 0) || (!ignore_hidden_file && tfn != "." && tfn != "..")) li.push_back(tfn);
BOOL r = FindNextFileW(re, &data);
if (!r) {
FindClose(re);
if (GetLastError() == ERROR_NO_MORE_FILES) break;
return false;
}
} while (1);
list = li;
return true;
}
template <typename T, typename ... Args> template <typename T, typename ... Args>
T fileop_internal(const char* fname, UINT codePage, T(*callback)(wchar_t* fn, Args... args), T failed, Args... args) { T fileop_internal(const char* fname, UINT codePage, T(*callback)(wchar_t* fn, Args... args), T failed, Args... args) {
int wlen; int wlen;
@@ -454,3 +479,54 @@ int64_t fileop::ftell(FILE* f) {
#endif #endif
#endif #endif
} }
bool fileop::listdir(std::string path, std::list<std::string>& filelist, bool ignore_hidden_file) {
#if _WIN32
if (!path.length()) path = ".";
path = str_util::str_replace(path, "/", "\\");
path = join(path, "*");
UINT cp[] = { CP_UTF8, CP_OEMCP, CP_ACP };
int i;
std::list<std::string> li;
for (i = 0; i < 3; i++) {
if (fileop_internal<bool, std::list<std::string>&, bool>(path.c_str(), cp[i], &listdir_internal, false, li, ignore_hidden_file)) {
filelist = li;
return true;
}
}
WIN32_FIND_DATAA data;
HANDLE re = FindFirstFileA(path.c_str(), &data);
if (re == INVALID_HANDLE_VALUE) return false;
std::string tfn;
do {
tfn = data.cFileName;
if ((ignore_hidden_file && tfn.find(".") != 0) || (!ignore_hidden_file && tfn != "." && tfn != "..")) li.push_back(tfn);
BOOL r = FindNextFileA(re, &data);
if (!r) {
FindClose(re);
if (GetLastError() == ERROR_NO_MORE_FILES) break;
return false;
}
} while (1);
filelist = li;
return true;
#else
DIR* dir = opendir(path.c_str());
if (!dir) return false;
struct dirent* d = readdir(dir);
std::list<std::string> li;
std::string tfn;
while (d) {
tfn = d->d_name;
if ((ignore_hidden_file && tfn.find(".") != 0) || (!ignore_hidden_file && tfn != "." && tfn != "..")) li.push_back(tfn);
d = readdir(dir);
}
if (errno) {
closedir(dir);
return false;
}
closedir(dir);
filelist = li;
return true;
#endif
}

View File

@@ -1,5 +1,6 @@
#ifndef _UTIL_FILEOP_H #ifndef _UTIL_FILEOP_H
#define _UTIL_FILEOP_H #define _UTIL_FILEOP_H
#include <list>
#include <string> #include <string>
#include <time.h> #include <time.h>
#include <stdint.h> #include <stdint.h>
@@ -154,5 +155,13 @@ namespace fileop {
* @return The current position * @return The current position
*/ */
int64_t ftell(FILE* f); int64_t ftell(FILE* f);
/**
* @brief List content of a directory.
* @param path The path of directory
* @param filelist Result
* @param ignore_hidden_file Ignore name starts with `.`
* @return true if successed.
*/
bool listdir(std::string path, std::list<std::string>& filelist, bool ignore_hidden_file = true);
} }
#endif #endif

View File

@@ -2,6 +2,10 @@
#include "cstr_util.h" #include "cstr_util.h"
#include <malloc.h> #include <malloc.h>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
bool str_util::tolowercase(std::string ori, std::string& result) { bool str_util::tolowercase(std::string ori, std::string& result) {
char* tmp = nullptr; char* tmp = nullptr;
auto re = cstr_tolowercase(ori.c_str(), ori.length(), &tmp); auto re = cstr_tolowercase(ori.c_str(), ori.length(), &tmp);
@@ -13,3 +17,15 @@ bool str_util::tolowercase(std::string ori, std::string& result) {
return false; return false;
} }
} }
std::string str_util::str_replace(std::string input, std::string pattern, std::string new_content) {
auto loc = input.find(pattern, 0);
auto len = pattern.length();
auto len2 = new_content.length();
while (loc != -1) {
input.replace(loc, len, new_content);
if (loc + len2 < input.length()) loc = input.find(pattern, max(0, loc + len2));
else break;
}
return input;
}

View File

@@ -9,5 +9,13 @@ namespace str_util {
* @return true if successed. * @return true if successed.
*/ */
bool tolowercase(std::string ori, std::string& result); bool tolowercase(std::string ori, std::string& result);
/**
* @brief Replace all pattern to new_content
* @param input Input string
* @param pattern Pattern
* @param new_content New content
* @return Result string
*/
std::string str_replace(std::string input, std::string pattern, std::string new_content);
} }
#endif #endif