From f55c54f7b4ae04336f6154d67f2ec0f2156e4e1e Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 22 May 2015 23:21:01 +0200 Subject: [PATCH] filesystem to experimental to avoid conflicts with fs_utillity --- include/nana/filesystem/filesystem.hpp | 5 +- source/filesystem/filesystem.cpp | 724 +++++++++++++------------ 2 files changed, 366 insertions(+), 363 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 3b8f3dd7..c117a797 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -46,7 +46,7 @@ // namespace std { namespace experimental { namespace filesystem { inline namespace v1 { -namespace nana +namespace nana { namespace experimental { namespace filesystem { @@ -73,7 +73,7 @@ namespace filesystem //enum class directory_options; // class filesystem_error; - enum class error { none = 0 }; + enum class error { none = 0 }; // deprecate ?? struct attribute // deprecate ?? { @@ -449,6 +449,7 @@ namespace filesystem }//end namespace filesystem +} //end namespace experimental }//end namespace nana #endif diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index f578afeb..07d297f3 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -36,407 +36,409 @@ #include #endif -namespace nana -{ -namespace filesystem -{ -//Because of No wide character version of POSIX +namespace nana { + namespace experimental + { + namespace filesystem + { + //Because of No wide character version of POSIX #if defined(NANA_LINUX) - typedef std::string string_t; - const char* splstr = "/\\"; + typedef std::string string_t; + const char* splstr = "/\\"; #else - typedef nana::string string_t; - const nana::char_t* splstr = STR("/\\"); + typedef nana::string string_t; + const nana::char_t* splstr = STR("/\\"); #endif - //class path - path::path(){} + //class path + path::path() {} - path::path(const nana::string& text) + path::path(const nana::string& text) #if defined(NANA_WINDOWS) - :text_(text) - { + : text_(text) + { #else - :text_(nana::charset(text)) - { + :text_(nana::charset(text)) + { #endif - auto pos = text_.find_last_of(splstr); - for(; (pos != string_t::npos) && (pos + 1 == text_.size()); pos = text_.find_last_of(splstr)) - text_.erase(pos); - } + auto pos = text_.find_last_of(splstr); + for (; (pos != string_t::npos) && (pos + 1 == text_.size()); pos = text_.find_last_of(splstr)) + text_.erase(pos); + } - bool path::empty() const - { + bool path::empty() const + { #if defined(NANA_WINDOWS) - return (::GetFileAttributes(text_.c_str()) == INVALID_FILE_ATTRIBUTES); + return (::GetFileAttributes(text_.c_str()) == INVALID_FILE_ATTRIBUTES); #elif defined(NANA_LINUX) - struct stat sta; - return (::stat(text_.c_str(), &sta) == -1); + struct stat sta; + return (::stat(text_.c_str(), &sta) == -1); #endif - } + } - path path::root() const - { - #if defined(NANA_WINDOWS) - return path(filesystem::root(text_)); - #elif defined(NANA_LINUX) - return path(filesystem::root(nana::charset(text_))); - #endif - } - - file_type path::what() const - { + path path::root() const + { #if defined(NANA_WINDOWS) - unsigned long attr = ::GetFileAttributes(text_.c_str()); - if(INVALID_FILE_ATTRIBUTES == attr) - return file_type:: not_found ; //?? - - if(FILE_ATTRIBUTE_DIRECTORY & attr) - return file_type::directory; - - return file_type::regular; + return path(filesystem::root(text_)); #elif defined(NANA_LINUX) - struct stat sta; - if(-1 == ::stat(text_.c_str(), &sta)) - return file_type:: not_found ; //?? + return path(filesystem::root(nana::charset(text_))); +#endif + } - if((S_IFDIR & sta.st_mode) == S_IFDIR) - return file_type::directory; + file_type path::what() const + { +#if defined(NANA_WINDOWS) + unsigned long attr = ::GetFileAttributes(text_.c_str()); + if (INVALID_FILE_ATTRIBUTES == attr) + return file_type::not_found; //?? + + if (FILE_ATTRIBUTE_DIRECTORY & attr) + return file_type::directory; - if((S_IFREG & sta.st_mode) == S_IFREG) return file_type::regular; +#elif defined(NANA_LINUX) + struct stat sta; + if (-1 == ::stat(text_.c_str(), &sta)) + return file_type::not_found; //?? - return file_type::none; + if ((S_IFDIR & sta.st_mode) == S_IFDIR) + return file_type::directory; + + if ((S_IFREG & sta.st_mode) == S_IFREG) + return file_type::regular; + + return file_type::none; #endif - } + } - nana::string path::name() const - { - string_t::size_type pos = text_.find_last_of(splstr); + nana::string path::name() const + { + string_t::size_type pos = text_.find_last_of(splstr); #if defined(NANA_WINDOWS) - return text_.substr(pos + 1); + return text_.substr(pos + 1); #else - return nana::charset(text_.substr(pos + 1)); -#endif - } - //end class path - - namespace detail - { - //rm_dir_recursive - //@brief: remove a directory, if it is not empty, recursively remove it's subfiles and sub directories - bool rm_dir_recursive(nana::string&& dir) - { - std::vector files; - nana::string path = dir; - path += '\\'; - - std::copy(directory_iterator(dir), directory_iterator(), std::back_inserter(files)); - - for(auto & f : files) - { - if(f.attr.directory) - rm_dir_recursive(path + f.path().name()); - else - rmfile((path + f.path().name()).c_str()); - } - - return rmdir(dir.c_str(), true); - } - - bool mkdir_helper(const nana::string& dir, bool & if_exist) - { -#if defined(NANA_WINDOWS) - if(::CreateDirectory(dir.c_str(), 0)) - { - if_exist = false; - return true; - } - - if_exist = (::GetLastError() == ERROR_ALREADY_EXISTS); -#elif defined(NANA_LINUX) - if(0 == ::mkdir(static_cast(nana::charset(dir)).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) - { - if_exist = false; - return true; - } - - if_exist = (errno == EEXIST); -#endif - return false; - } - -#if defined(NANA_WINDOWS) - void filetime_to_c_tm(FILETIME& ft, struct tm& t) - { - FILETIME local_file_time; - if(::FileTimeToLocalFileTime(&ft, &local_file_time)) - { - SYSTEMTIME st; - ::FileTimeToSystemTime(&local_file_time, &st); - t.tm_year = st.wYear - 1900; - t.tm_mon = st.wMonth - 1; - t.tm_mday = st.wDay; - t.tm_wday = st.wDayOfWeek - 1; - t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay); - - t.tm_hour = st.wHour; - t.tm_min = st.wMinute; - t.tm_sec = st.wSecond; - } - } -#endif - }//end namespace detail - - bool file_attrib(const nana::string& file, attribute& attr) - { -#if defined(NANA_WINDOWS) - WIN32_FILE_ATTRIBUTE_DATA fad; - if(::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &fad)) - { - LARGE_INTEGER li; - li.u.LowPart = fad.nFileSizeLow; - li.u.HighPart = fad.nFileSizeHigh; - attr.size = li.QuadPart; - attr.directory = (0 != (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); - detail::filetime_to_c_tm(fad.ftLastWriteTime, attr.modified); - return true; - } -#elif defined(NANA_LINUX) - struct stat fst; - if(0 == ::stat(static_cast(nana::charset(file)).c_str(), &fst)) - { - attr.bytes = fst.st_size; - attr.is_directory = (0 != (040000 & fst.st_mode)); - attr.modified = *(::localtime(&fst.st_ctime)); - return true; - } -#endif - return false; - } - - uintmax_t file_size(const nana::string& file) - { -#if defined(NANA_WINDOWS) - //Some compilation environment may fail to link to GetFileSizeEx - typedef BOOL (__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER); - GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx")); - if(get_file_size_ex) - { - HANDLE handle = ::CreateFile(file.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if(INVALID_HANDLE_VALUE != handle) - { - LARGE_INTEGER li; - if(!get_file_size_ex(handle, &li)) - li.QuadPart = 0; - - ::CloseHandle(handle); - return li.QuadPart; - } - } - return 0; -#elif defined(NANA_LINUX) - FILE * stream = ::fopen(static_cast(nana::charset(file)).c_str(), "rb"); - long long size = 0; - if(stream) - { - fseeko64(stream, 0, SEEK_END); - size = ftello64(stream); - fclose(stream); - } - return size; -#endif - } - - bool modified_file_time(const nana::string& file, struct tm& t) - { -#if defined(NANA_WINDOWS) - WIN32_FILE_ATTRIBUTE_DATA attr; - if(::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &attr)) - { - FILETIME local_file_time; - if(::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time)) - { - SYSTEMTIME st; - ::FileTimeToSystemTime(&local_file_time, &st); - t.tm_year = st.wYear - 1900; - t.tm_mon = st.wMonth - 1; - t.tm_mday = st.wDay; - t.tm_wday = st.wDayOfWeek - 1; - t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay); - - t.tm_hour = st.wHour; - t.tm_min = st.wMinute; - t.tm_sec = st.wSecond; - return true; - } - } -#elif defined(NANA_LINUX) - struct stat attr; - if(0 == ::stat(static_cast(nana::charset(file)).c_str(), &attr)) - { - t = *(::localtime(&attr.st_ctime)); - return true; - } -#endif - return false; - } - - bool create_directory(const nana::string& path, bool & if_exist) - { - if_exist = false; - if(path.size() == 0) return false; - - nana::string root; -#if defined(NANA_WINDOWS) - if(path.size() > 3 && path[1] == STR(':')) - root = path.substr(0, 3); -#elif defined(NANA_LINUX) - if(path[0] == STR('/')) - root = '/'; -#endif - bool mkstat = false; - std::size_t beg = root.size(); - - while(true) - { - beg = path.find_first_not_of(STR("/\\"), beg); - if(beg == path.npos) - break; - - std::size_t pos = path.find_first_of(STR("/\\"), beg + 1); - if(pos != path.npos) - { - root += path.substr(beg, pos - beg); - - mkstat = detail::mkdir_helper(root, if_exist); - if(mkstat == false && if_exist == false) - return false; - -#if defined(NANA_WINDOWS) - root += STR('\\'); -#elif defined(NANA_LINUX) - root += STR('/'); + return nana::charset(text_.substr(pos + 1)); #endif } - else + //end class path + + namespace detail { - if(beg + 1 < path.size()) + //rm_dir_recursive + //@brief: remove a directory, if it is not empty, recursively remove it's subfiles and sub directories + bool rm_dir_recursive(nana::string&& dir) { - root += path.substr(beg); - mkstat = detail::mkdir_helper(root, if_exist); + std::vector files; + nana::string path = dir; + path += '\\'; + + std::copy(directory_iterator(dir), directory_iterator(), std::back_inserter(files)); + + for (auto & f : files) + { + if (f.attr.directory) + rm_dir_recursive(path + f.path().name()); + else + rmfile((path + f.path().name()).c_str()); + } + + return rmdir(dir.c_str(), true); } - break; - } - beg = pos + 1; - } - return mkstat; - } - bool rmfile(const nana::char_t* file) - { + bool mkdir_helper(const nana::string& dir, bool & if_exist) + { #if defined(NANA_WINDOWS) - bool ret = false; - if(file) - { - ret = (::DeleteFile(file) == TRUE); - if(!ret) - ret = (ERROR_FILE_NOT_FOUND == ::GetLastError()); - } + if (::CreateDirectory(dir.c_str(), 0)) + { + if_exist = false; + return true; + } - return ret; + if_exist = (::GetLastError() == ERROR_ALREADY_EXISTS); #elif defined(NANA_LINUX) - if(std::remove(static_cast(nana::charset(file)).c_str())) - return (errno == ENOENT); - return true; -#endif - } + if (0 == ::mkdir(static_cast(nana::charset(dir)).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) + { + if_exist = false; + return true; + } + + if_exist = (errno == EEXIST); +#endif + return false; + } - bool rmdir(const nana::char_t* dir, bool fails_if_not_empty) - { - bool ret = false; - if(dir) - { #if defined(NANA_WINDOWS) - ret = (::RemoveDirectory(dir) == TRUE); - if(!fails_if_not_empty && (::GetLastError() == ERROR_DIR_NOT_EMPTY)) - ret = detail::rm_dir_recursive(dir); -#elif defined(NANA_LINUX) - std::string mbstr = nana::charset(dir); - if(::rmdir(mbstr.c_str())) - { - if(!fails_if_not_empty && (errno == EEXIST || errno == ENOTEMPTY)) - ret = detail::rm_dir_recursive(dir); - } - else - ret = true; + void filetime_to_c_tm(FILETIME& ft, struct tm& t) + { + FILETIME local_file_time; + if (::FileTimeToLocalFileTime(&ft, &local_file_time)) + { + SYSTEMTIME st; + ::FileTimeToSystemTime(&local_file_time, &st); + t.tm_year = st.wYear - 1900; + t.tm_mon = st.wMonth - 1; + t.tm_mday = st.wDay; + t.tm_wday = st.wDayOfWeek - 1; + t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay); + + t.tm_hour = st.wHour; + t.tm_min = st.wMinute; + t.tm_sec = st.wSecond; + } + } #endif - } - return ret; - } + }//end namespace detail - nana::string root(const nana::string& path) - { - std::size_t index = path.size(); - - if(index) - { - const nana::char_t * str = path.c_str(); - - for(--index; index > 0; --index) + bool file_attrib(const nana::string& file, attribute& attr) { - nana::char_t c = str[index]; - if(c != '\\' && c != '/') - break; - } - - for(--index; index > 0; --index) - { - nana::char_t c = str[index]; - if(c == '\\' || c == '/') - break; - } - } - - return index?path.substr(0, index + 1):nana::string(); - } - - nana::string path_user() - { #if defined(NANA_WINDOWS) - nana::char_t path[MAX_PATH]; - if(SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, path))) - return path; + WIN32_FILE_ATTRIBUTE_DATA fad; + if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &fad)) + { + LARGE_INTEGER li; + li.u.LowPart = fad.nFileSizeLow; + li.u.HighPart = fad.nFileSizeHigh; + attr.size = li.QuadPart; + attr.directory = (0 != (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); + detail::filetime_to_c_tm(fad.ftLastWriteTime, attr.modified); + return true; + } #elif defined(NANA_LINUX) - const char * s = ::getenv("HOME"); - if(s) - return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8); + struct stat fst; + if (0 == ::stat(static_cast(nana::charset(file)).c_str(), &fst)) + { + attr.bytes = fst.st_size; + attr.is_directory = (0 != (040000 & fst.st_mode)); + attr.modified = *(::localtime(&fst.st_ctime)); + return true; + } #endif - return nana::string(); - } - - path current_path() - { -#if defined(NANA_WINDOWS) - nana::char_t buf[MAX_PATH]; - DWORD len = ::GetCurrentDirectory(MAX_PATH, buf); - if(len) - { - if(len > MAX_PATH) - { - nana::char_t * p = new nana::char_t[len + 1]; - ::GetCurrentDirectory(len + 1, p); - nana::string s = p; - delete [] p; - return s; + return false; } - return buf; - } + + uintmax_t file_size(const nana::string& file) + { +#if defined(NANA_WINDOWS) + //Some compilation environment may fail to link to GetFileSizeEx + typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER); + GetFileSizeEx_fptr_t get_file_size_ex = reinterpret_cast(::GetProcAddress(::GetModuleHandleA("Kernel32.DLL"), "GetFileSizeEx")); + if (get_file_size_ex) + { + HANDLE handle = ::CreateFile(file.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (INVALID_HANDLE_VALUE != handle) + { + LARGE_INTEGER li; + if (!get_file_size_ex(handle, &li)) + li.QuadPart = 0; + + ::CloseHandle(handle); + return li.QuadPart; + } + } + return 0; #elif defined(NANA_LINUX) - const char * s = ::getenv("PWD"); - if(s) - return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8); + FILE * stream = ::fopen(static_cast(nana::charset(file)).c_str(), "rb"); + long long size = 0; + if (stream) + { + fseeko64(stream, 0, SEEK_END); + size = ftello64(stream); + fclose(stream); + } + return size; #endif - return nana::string(); - } -}//end namespace filesystem + } + + bool modified_file_time(const nana::string& file, struct tm& t) + { +#if defined(NANA_WINDOWS) + WIN32_FILE_ATTRIBUTE_DATA attr; + if (::GetFileAttributesEx(file.c_str(), GetFileExInfoStandard, &attr)) + { + FILETIME local_file_time; + if (::FileTimeToLocalFileTime(&attr.ftLastWriteTime, &local_file_time)) + { + SYSTEMTIME st; + ::FileTimeToSystemTime(&local_file_time, &st); + t.tm_year = st.wYear - 1900; + t.tm_mon = st.wMonth - 1; + t.tm_mday = st.wDay; + t.tm_wday = st.wDayOfWeek - 1; + t.tm_yday = nana::date::day_in_year(st.wYear, st.wMonth, st.wDay); + + t.tm_hour = st.wHour; + t.tm_min = st.wMinute; + t.tm_sec = st.wSecond; + return true; + } + } +#elif defined(NANA_LINUX) + struct stat attr; + if (0 == ::stat(static_cast(nana::charset(file)).c_str(), &attr)) + { + t = *(::localtime(&attr.st_ctime)); + return true; + } +#endif + return false; + } + + bool create_directory(const nana::string& path, bool & if_exist) + { + if_exist = false; + if (path.size() == 0) return false; + + nana::string root; +#if defined(NANA_WINDOWS) + if (path.size() > 3 && path[1] == STR(':')) + root = path.substr(0, 3); +#elif defined(NANA_LINUX) + if (path[0] == STR('/')) + root = '/'; +#endif + bool mkstat = false; + std::size_t beg = root.size(); + + while (true) + { + beg = path.find_first_not_of(STR("/\\"), beg); + if (beg == path.npos) + break; + + std::size_t pos = path.find_first_of(STR("/\\"), beg + 1); + if (pos != path.npos) + { + root += path.substr(beg, pos - beg); + + mkstat = detail::mkdir_helper(root, if_exist); + if (mkstat == false && if_exist == false) + return false; + +#if defined(NANA_WINDOWS) + root += STR('\\'); +#elif defined(NANA_LINUX) + root += STR('/'); +#endif + } + else + { + if (beg + 1 < path.size()) + { + root += path.substr(beg); + mkstat = detail::mkdir_helper(root, if_exist); + } + break; + } + beg = pos + 1; + } + return mkstat; + } + + bool rmfile(const nana::char_t* file) + { +#if defined(NANA_WINDOWS) + bool ret = false; + if (file) + { + ret = (::DeleteFile(file) == TRUE); + if (!ret) + ret = (ERROR_FILE_NOT_FOUND == ::GetLastError()); + } + + return ret; +#elif defined(NANA_LINUX) + if (std::remove(static_cast(nana::charset(file)).c_str())) + return (errno == ENOENT); + return true; +#endif + } + + bool rmdir(const nana::char_t* dir, bool fails_if_not_empty) + { + bool ret = false; + if (dir) + { +#if defined(NANA_WINDOWS) + ret = (::RemoveDirectory(dir) == TRUE); + if (!fails_if_not_empty && (::GetLastError() == ERROR_DIR_NOT_EMPTY)) + ret = detail::rm_dir_recursive(dir); +#elif defined(NANA_LINUX) + std::string mbstr = nana::charset(dir); + if (::rmdir(mbstr.c_str())) + { + if (!fails_if_not_empty && (errno == EEXIST || errno == ENOTEMPTY)) + ret = detail::rm_dir_recursive(dir); + } + else + ret = true; +#endif + } + return ret; + } + + nana::string root(const nana::string& path) + { + std::size_t index = path.size(); + + if (index) + { + const nana::char_t * str = path.c_str(); + + for (--index; index > 0; --index) + { + nana::char_t c = str[index]; + if (c != '\\' && c != '/') + break; + } + + for (--index; index > 0; --index) + { + nana::char_t c = str[index]; + if (c == '\\' || c == '/') + break; + } + } + + return index ? path.substr(0, index + 1) : nana::string(); + } + + nana::string path_user() + { +#if defined(NANA_WINDOWS) + nana::char_t path[MAX_PATH]; + if (SUCCEEDED(SHGetFolderPath(0, CSIDL_PROFILE, 0, SHGFP_TYPE_CURRENT, path))) + return path; +#elif defined(NANA_LINUX) + const char * s = ::getenv("HOME"); + if (s) + return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8); +#endif + return nana::string(); + } + + path current_path() + { +#if defined(NANA_WINDOWS) + nana::char_t buf[MAX_PATH]; + DWORD len = ::GetCurrentDirectory(MAX_PATH, buf); + if (len) + { + if (len > MAX_PATH) + { + nana::char_t * p = new nana::char_t[len + 1]; + ::GetCurrentDirectory(len + 1, p); + nana::string s = p; + delete[] p; + return s; + } + return buf; + } +#elif defined(NANA_LINUX) + const char * s = ::getenv("PWD"); + if (s) + return nana::charset(std::string(s, std::strlen(s)), nana::unicode::utf8); +#endif + return nana::string(); + } + }//end namespace filesystem + } //end namespace experimental }//end namespace nana