22 #include <dirent/dirent.h>
26 #define PATH_MAX MAX_PATH
38 #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
42 namespace fs = std::__fs::filesystem;
44 #include <experimental/filesystem>
45 namespace fs = std::experimental::filesystem;
50 namespace filesystem {
52 std::string
JoinPath(
const std::string &path_component1,
53 const std::string &path_component2) {
55 return (
path / path_component2).string();
58 std::string
JoinPath(
const std::vector<std::string> &path_components) {
60 for (
const auto &pc : path_components) {
67 if (
const char *env_p = std::getenv(env_var.c_str())) {
75 std::string home_dir =
"";
107 if (str.length() > 0) {
108 if (str.back() !=
'/') {
123 if (ext.at(0) !=
'.') {
128 std::string ext_lower =
ToLower(ext);
129 if (file_name.size() >= ext_lower.size() &&
130 file_name.substr(file_name.size() - ext_lower.size(),
131 ext_lower.size()) == ext_lower) {
145 if (parts.size() == 1) {
150 for (
size_t i = 0; i < parts.size() - 1; ++i) {
151 *root += parts[i] +
".";
155 if (parts.back() ==
"") {
158 *ext =
"." + parts.back();
163 bool CopyFile(
const std::string &from,
const std::string &to) {
168 return CopyA(from, to);
172 std::ifstream src(from, std::ios::binary);
182 return CopyA(from, to);
185 std::ofstream dst(to, std::ios::binary);
202 bool CopyDir(
const std::string &from,
const std::string &to) {
203 DIR *directory = opendir(from.c_str());
204 if (directory ==
nullptr) {
211 struct dirent *entry;
212 while ((entry = readdir(directory)) !=
nullptr) {
214 if (!strcmp(entry->d_name,
".") || !strcmp(entry->d_name,
"..")) {
217 const std::string sub_path_from = from +
"/" + entry->d_name;
218 const std::string sub_path_to = to +
"/" + entry->d_name;
219 if (entry->d_type == DT_DIR) {
220 ret &=
CopyDir(sub_path_from, sub_path_to);
222 ret &=
CopyFile(sub_path_from, sub_path_to);
236 bool CopyA(
const std::string &src_path,
const std::string &dst_path) {
239 fs::copy_options::recursive |
240 fs::copy_options::overwrite_existing);
241 }
catch (std::exception &e) {
249 bool Copy(
const std::string &from,
250 const std::string &to,
251 bool include_parent_dir,
252 const std::string &extname) {
254 if (extname.empty()) {
255 if (include_parent_dir) {
262 std::vector<std::string> filtered_files;
267 for (
const auto &fn : filtered_files) {
282 size_t dot_pos =
filename.find_last_of(
".");
283 if (dot_pos >=
filename.length())
return "";
285 if (
filename.find_first_of(
"/\\", dot_pos) != std::string::npos)
return "";
287 std::string filename_ext =
filename.substr(dot_pos + 1);
289 std::transform(filename_ext.begin(), filename_ext.end(),
290 filename_ext.begin(), ::tolower);
296 size_t dot_pos =
filename.find_last_of(
".");
302 size_t slash_pos =
filename.find_last_of(
"/\\");
303 if (slash_pos == std::string::npos) {
306 return filename.substr(slash_pos + 1);
315 size_t slash_pos =
filename.find_last_of(
"/\\");
316 if (slash_pos == std::string::npos) {
319 return filename.substr(0, slash_pos + 1);
324 if (directory.empty()) {
326 }
else if (directory.back() !=
'/' && directory.back() !=
'\\') {
327 return directory +
"/";
334 char buff[PATH_MAX + 1];
335 char *flag =
nullptr;
337 flag = _getcwd(buff, PATH_MAX + 1);
339 flag = getcwd(buff, PATH_MAX + 1);
342 return std::string(buff);
344 return std::string(
"");
349 auto SplitByPathSeparators = [](
const std::string &
path) {
350 std::vector<std::string> components;
354 while (end <
path.size()) {
356 while (end <
path.size() &&
path[end] !=
'\\' &&
361 components.push_back(
path.substr(start, end - start));
363 if (end <
path.size()) {
371 auto pathComponents = SplitByPathSeparators(
path.c_str());
374 if (pathComponents.empty()) {
379 pathComponents.push_back(
".");
383 char firstChar =
path[0];
384 bool isRelative = (firstChar !=
'/');
385 bool isWindowsPath =
false;
387 if (isRelative && pathComponents[0].
size() >= 2 &&
388 ((firstChar >=
'a' && firstChar <=
'z') ||
389 (firstChar >=
'A' && firstChar <=
'Z')) &&
390 pathComponents[0][1] ==
':') {
392 isWindowsPath =
true;
395 std::vector<std::string> components;
398 auto cwdComponents = SplitByPathSeparators(cwd);
399 components.insert(components.end(), cwdComponents.begin(),
400 cwdComponents.end());
402 isWindowsPath =
true;
407 if (!isWindowsPath) {
408 components.insert(components.begin(),
"/");
411 for (
auto &dir : pathComponents) {
413 }
else if (dir ==
"..") {
414 components.pop_back();
416 components.push_back(dir);
424 return fs::temp_directory_path().string();
429 return (_chdir(directory.c_str()) == 0);
431 return (chdir(directory.c_str()) == 0);
437 DWORD attributes = GetFileAttributes(
filename.c_str());
438 if (attributes == INVALID_FILE_ATTRIBUTES)
return false;
439 return !(attributes & FILE_ATTRIBUTE_DIRECTORY);
441 if (0 != access(
filename.c_str(), F_OK)) {
445 struct stat file_stat;
446 if (0 > stat(
filename.c_str(), &file_stat)) {
447 perror(
"get file stat error");
450 return S_ISREG(file_stat.st_mode);
456 DWORD attributes = GetFileAttributes(directory.c_str());
457 if (attributes == INVALID_FILE_ATTRIBUTES)
return false;
458 return (attributes & FILE_ATTRIBUTE_DIRECTORY);
460 if (0 != access(directory.c_str(), F_OK)) {
464 struct stat file_stat;
465 if (0 > stat(directory.c_str(), &file_stat)) {
466 perror(
"get directory stat error");
469 return S_ISDIR(file_stat.st_mode);
474 return fs::is_directory(directory);
481 return fs::is_empty(directory);
493 return (_mkdir(directory.c_str()) == 0);
495 return (mkdir(directory.c_str(), S_IRWXU) == 0);
501 size_t curr_pos = full_path.find_first_of(
"/\\", 1);
502 while (curr_pos != std::string::npos) {
503 std::string subdir = full_path.substr(0, curr_pos + 1);
509 curr_pos = full_path.find_first_of(
"/\\", curr_pos + 1);
515 std::error_code
error;
516 if (fs::remove_all(directory,
error) ==
static_cast<std::uintmax_t
>(-1)) {
529 return (std::remove(
filename.c_str()) == 0);
533 std::vector<std::string> &subdirs,
534 std::vector<std::string> &filenames) {
535 if (directory.empty()) {
541 dir = opendir(directory.c_str());
546 while ((ent = readdir(dir)) !=
NULL) {
547 const std::string file_name = ent->d_name;
548 if (file_name[0] ==
'.')
continue;
549 std::string full_file_name =
551 if (stat(full_file_name.c_str(), &st) == -1)
continue;
552 if (S_ISDIR(st.st_mode))
553 subdirs.push_back(full_file_name);
554 else if (S_ISREG(st.st_mode))
555 filenames.push_back(full_file_name);
562 std::vector<std::string> &filenames) {
563 std::vector<std::string> subdirs;
568 const std::string &extname,
569 std::vector<std::string> &filenames) {
570 std::vector<std::string> all_files;
574 std::string ext_in_lower = extname;
575 std::transform(ext_in_lower.begin(), ext_in_lower.end(),
576 ext_in_lower.begin(), ::tolower);
578 for (
const auto &fn : all_files) {
580 filenames.push_back(fn);
587 const std::string &directory,
588 std::function<
bool(
const std::string &)> is_match) {
589 std::vector<std::string> matches;
591 std::vector<std::string> subdirs;
592 std::vector<std::string> files;
594 for (
auto &f : files) {
596 matches.push_back(f);
599 for (
auto &d : subdirs) {
601 if (!submatches.empty()) {
602 matches.insert(matches.end(), submatches.begin(), submatches.end());
612 fp = fopen(
filename.c_str(), mode.c_str());
614 std::wstring filename_w;
616 int newSize = MultiByteToWideChar(CP_UTF8, 0,
filename.c_str(),
617 static_cast<int>(
filename.length()),
618 const_cast<wchar_t *
>(filename_w.c_str()),
619 static_cast<int>(
filename.length()));
620 filename_w.resize(newSize);
621 std::wstring mode_w(mode.begin(), mode.end());
622 fp = _wfopen(filename_w.c_str(), mode_w.c_str());
630 return "Operation not permitted";
632 return "Access denied";
635 return "Resource unavailable, try again";
641 return "File already exists";
643 return "Bad filename pointer";
645 return "open() interrupted by a signal";
649 return "Too many symlinks, could be a loop";
651 return "Process is out of file descriptors";
653 return "Filename is too long";
655 return "File system table is full";
657 return "No such file or directory";
659 return "No space available to create file";
663 return "File is too big";
665 return "Can't modify file on read-only filesystem";
666 #if EWOULDBLOCK != EAGAIN
668 return "Operation would block calling process";
672 s <<
"IO error " << errnoVal <<
" (see sys/errno.h)";
679 std::vector<char> &
bytes,
680 std::string *errorStr) {
695 if (fseek(file, 0,
SEEK_END) != 0) {
697 if (errno && errno != EWOULDBLOCK) {
707 const std::size_t filesize =
static_cast<std::size_t
>(ftell(file));
710 bytes.resize(filesize);
711 const std::size_t
result = fread(
bytes.data(), 1, filesize, file);
727 const std::vector<std::string> &folder_names) {
728 for (
const auto &folder_name : folder_names) {
729 const std::string folder_path =
JoinPath(
path, folder_name);
764 int64_t pos = ftell(file_);
777 if (fgetpos(file_, &prevpos)) {
786 if (fsetpos(file_, &prevpos)) {
798 if (fgetpos(file_, &prevpos)) {
806 int64_t num_lines = 0;
808 while (EOF != (c = getc(file_))) {
813 if (fsetpos(file_, &prevpos)) {
824 if (line_buffer_.empty()) {
827 if (!fgets(line_buffer_.data(),
int(line_buffer_.size()), file_)) {
833 "CFile::ReadLine() fgets returned NULL, ferror is not set, "
838 if (strlen(line_buffer_.data()) == line_buffer_.size() - 1) {
842 line_buffer_.size() - 2);
844 return line_buffer_.data();
851 size_t elems = fread(data, elem_size, num_elems, file_);
855 if (elems < num_elems) {
858 "CFile::ReadData() fread short read, ferror not set, feof "
std::string GetError()
Returns the last encountered error for this file.
bool Open(const std::string &filename, const std::string &mode)
Open a file.
~CFile()
The destructor closes the file automatically.
int64_t CurPos()
Returns current position in the file (ftell).
void Close()
Close the file.
int64_t GetFileSize()
Returns the file size in bytes.
int64_t GetNumLines()
Returns the number of lines in the file.
size_t ReadData(T *data, size_t num_elems)
#define DEFAULT_IO_BUFFER_SIZE
static void error(char *msg)
static const std::string path
bool ChangeWorkingDirectory(const std::string &directory)
bool ListFilesInDirectory(const std::string &directory, std::vector< std::string > &filenames)
bool RemoveFile(const std::string &filename)
std::string GetWorkingDirectory()
std::vector< std::string > FindFilesRecursively(const std::string &directory, std::function< bool(const std::string &)> is_match)
bool IsDirectory(const std::string &directory)
std::string EnsureTrailingSlash(const std::string &str)
bool DeleteDirectory(const std::string &directory)
bool Copy(const std::string &from, const std::string &to, bool include_parent_dir=false, const std::string &extname="")
Copy a file or directory.
bool FReadToBuffer(const std::string &path, std::vector< char > &bytes, std::string *errorStr)
bool MakeDirectoryHierarchy(const std::string &directory)
bool CopyFile(const std::string &from, const std::string &to)
Copy a file.
bool DirectoryIsEmpty(const std::string &directory)
std::string GetFileParentDirectory(const std::string &filename)
std::string GetEnvVar(const std::string &env_var)
bool ListFilesInDirectoryWithExtension(const std::string &directory, const std::string &extname, std::vector< std::string > &filenames)
void SplitFileExtension(const std::string &path, std::string *root, std::string *ext)
std::string GetTempDirectoryPath()
bool DirectoryExists(const std::string &directory)
std::string JoinPath(const std::vector< std::string > &path_components)
std::string GetIOErrorString(const int errnoVal)
std::string GetFileBaseName(const std::string &filename)
bool CopyDir(const std::string &from, const std::string &to)
Copy a directory.
bool EnsureDirectory(const std::string &directory_path)
Check if a specified directory specified by directory_path exists. If not, recursively create the dir...
std::string GetRegularizedDirectoryName(const std::string &directory)
std::string GetFileNameWithoutExtension(const std::string &filename)
std::string GetFileExtensionInLowerCase(const std::string &filename)
bool FileExists(const std::string &filename)
bool IsFile(const std::string &filename)
std::string JoinPaths(T const &...paths)
std::vector< std::string > GetPathComponents(const std::string &path)
bool MakeDirectory(const std::string &directory)
FILE * FOpen(const std::string &filename, const std::string &mode)
std::string AddIfExist(const std::string &path, const std::vector< std::string > &folder_names)
bool HasFileExtension(const std::string &file_name, const std::string &ext)
std::string GetHomeDirectory()
Get the HOME directory for the user.
std::string GetFileNameWithoutDirectory(const std::string &filename)
bool CopyA(const std::string &src_path, const std::string &dst_path)
bool ListDirectory(const std::string &directory, std::vector< std::string > &subdirs, std::vector< std::string > &filenames)
std::string ToLower(const std::string &s)
Convert string to the lower case.
std::vector< std::string > StringSplit(const std::string &str, const std::string &delimiters=" ", bool trim_empty_str=true)
Generic file read and write utility for python interface.