From f4ceafbe6cc48bd31947f59aed2d59fb57110489 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 10 May 2015 15:28:59 +0200 Subject: [PATCH 01/12] testing and doxy comment audio and screen --- include/nana/audio/player.hpp | 5 ++++- include/nana/gui/screen.hpp | 17 ++++++++++++++--- source/audio/detail/audio_stream.cpp | 3 ++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/nana/audio/player.hpp b/include/nana/audio/player.hpp index 278e0ecc..24378214 100644 --- a/include/nana/audio/player.hpp +++ b/include/nana/audio/player.hpp @@ -4,7 +4,10 @@ #include namespace nana{ namespace audio -{ /// play an audio file in Windows WAV format +{ /// class player + /// \brief play an audio file in PCM Windows WAV format + /// + /// \include audio_player.cpp class player : private nana::noncopyable { diff --git a/include/nana/gui/screen.hpp b/include/nana/gui/screen.hpp index ef9126e8..06c344ee 100644 --- a/include/nana/gui/screen.hpp +++ b/include/nana/gui/screen.hpp @@ -34,27 +34,38 @@ namespace nana virtual const ::nana::rectangle& workarea() const = 0; }; + /// Provides some functions to get the metrics of the monitors \include screen.cpp class screen { struct implement; public: - static ::nana::size desktop_size(); - static ::nana::size primary_monitor_size(); + /// gets the size in pixel of the whole virtual desktop + static ::nana::size desktop_size(); + + /// gets the resolution in pixel of the primary monitor, + /// if there is only one monitor installed in the system, + /// the return value of primary_monitor_size is equal to desktop_size's. + static ::nana::size primary_monitor_size(); + screen(); /// Reload has no preconditions, it's safe to call on moved-from void reload(); - /// Returns the number of display monitors + /// Returns the number of display monitors installed in the system std::size_t count() const; + /// gets the display monitor that contains the specified point display& from_point(const point&); + + /// gets the display monitor that contains the specified window display& from_window(window); display& get_display(std::size_t index) const; display& get_primary() const; + /// applies a given function to all display monitors void for_each(std::function) const; private: std::shared_ptr impl_; diff --git a/source/audio/detail/audio_stream.cpp b/source/audio/detail/audio_stream.cpp index 96def3d9..998b85bf 100644 --- a/source/audio/detail/audio_stream.cpp +++ b/source/audio/detail/audio_stream.cpp @@ -8,7 +8,8 @@ namespace nana{ namespace audio //class audio_stream bool audio_stream::open(const nana::string& file) { - fs_.open(static_cast(nana::charset(file)), std::ios::binary); + std::string fname{nana::charset(file)};//static_cast() + fs_.open(fname, std::ios::binary); if(fs_) { wave_spec::master_riff_chunk riff; From 7117cc03b0276c5dd110ec390aa8fedb989f1ede Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Wed, 20 May 2015 12:42:53 +0200 Subject: [PATCH 02/12] adapting nana filesystem to std --- build/vc2013/nana.vcxproj | 3 + build/vc2013/nana.vcxproj.filters | 5 + include/nana/filesystem/filesystem.hpp | 272 +++++++++++++++++++++++++ 3 files changed, 280 insertions(+) create mode 100644 include/nana/filesystem/filesystem.hpp diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj index 7e216758..5f16d613 100644 --- a/build/vc2013/nana.vcxproj +++ b/build/vc2013/nana.vcxproj @@ -247,6 +247,9 @@ + + + diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters index f0f82981..1b098164 100644 --- a/build/vc2013/nana.vcxproj.filters +++ b/build/vc2013/nana.vcxproj.filters @@ -301,4 +301,9 @@ Source Files\nana\gui\widgets + + + Header Files + + \ No newline at end of file diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp new file mode 100644 index 00000000..bfdd1a71 --- /dev/null +++ b/include/nana/filesystem/filesystem.hpp @@ -0,0 +1,272 @@ +/* + * A filesystem Implementation + * Copyright(C) 2003 Jinhao(cnjinhao@hotmail.com) + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * @file: stdex/filesystem/filesystem.hpp + * @description: + * file_iterator is a toolkit for applying each file and directory in a + * specified path. + */ + +// http://en.cppreference.com/w/cpp/experimental/fs +// http://cpprocks.com/introduction-to-tr2-filesystem-library-in-vs2012/ --- TR2 filesystem in VS2012 +// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.140%29.aspx --- C++ 14, the header VS2015 +// https://msdn.microsoft.com/en-us/library/hh874694%28v=vs.120%29.aspx --- header VS2013 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf --- last pdf of std draft N4100 2014-07-04 +// http://cplusplus.github.io/filesystem-ts/working-draft.html --- in html format +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4099.html --- in html format +// http://article.gmane.org/gmane.comp.lib.boost.devel/256220 --- The filesystem TS unanimously approved by ISO. +// http://theboostcpplibraries.com/boost.filesystem --- Boost docs +// http://www.boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm --- +// http://www.boost.org/doc/libs/1_34_0/libs/filesystem/doc/index.htm +// http://www.boost.org/doc/libs/1_58_0/boost/filesystem.hpp + + +#ifndef NANA_FILESYSTEM_HPP +#define NANA_FILESYSTEM_HPP +#include +#include + +#include + +#ifdef NANA_WINDOWS + #include + typedef HANDLE find_handle_t; +#elif defined(NANA_LINUX) + #include + #include + #include + typedef DIR* find_handle_t; +#endif + + // namespace std { namespace experimental { namespace filesystem { inline namespace v1 { + +namespace nana +{ +namespace filesystem +{ + struct fileinfo + { + fileinfo(); +#ifdef NANA_WINDOWS + fileinfo(const WIN32_FIND_DATA& wfd); +#elif NANA_LINUX + fileinfo(const nana::string& filename, const struct stat &); +#endif + nana::string name; + + unsigned long size; + bool directory; + }; + + + /// an iterator for a sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator + //template + class directory_iterator :public std::iterator + { + public: + typedef fileinfo value_type; + + directory_iterator():end_(true), handle_(nullptr){} + + directory_iterator(const nana::string& file_path) + :end_(false), handle_(nullptr) + { + _m_prepare(file_path); + } + + const value_type& + operator*() const { return value_; } + + const value_type* + operator->() const { return &(operator*()); } + + directory_iterator& operator++() + { _m_read(); return *this; } + + directory_iterator operator++(int) + { + directory_iterator tmp = *this; + _m_read(); + return tmp; + } + + bool equal(const directory_iterator& x) const + { + if(end_ && (end_ == x.end_)) return true; + return (value_.name == x.value_.name); + } + private: + template + static bool _m_ignore(const Char * p) + { + while(*p == '.') + ++p; + return (*p == 0); + } + + void _m_prepare(const nana::string& file_path) + { + #if defined(NANA_WINDOWS) + path_ = file_path; + auto pat = file_path; + DWORD attr = ::GetFileAttributes(pat.data()); + if((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY)) + pat += STR("\\*"); + + ::HANDLE handle = ::FindFirstFile(pat.data(), &wfd_); + + if(handle == INVALID_HANDLE_VALUE) + { + end_ = true; + return; + } + + while(_m_ignore(wfd_.cFileName)) + { + if(::FindNextFile(handle, &wfd_) == 0) + { + end_ = true; + ::FindClose(handle); + return; + } + } + value_ = value_type(wfd_); + #elif defined(NANA_LINUX) + path_ = nana::charset(file_path); + if(path_.size() && (path_[path_.size() - 1] != '/')) + path_ += '/'; + find_handle_t handle = opendir(path_.c_str()); + end_ = true; + if(handle) + { + struct dirent * dnt = readdir(handle); + if(dnt) + { + while(_m_ignore(dnt->d_name)) + { + dnt = readdir(handle); + if(dnt == 0) + { + closedir(handle); + return; + } + } + + struct stat fst; + if(stat((path_ + dnt->d_name).c_str(), &fst) == 0) + { + value_ = value_type(nana::charset(dnt->d_name), fst); + } + else + { + value_.name = nana::charset(dnt->d_name); + value_.size = 0; + value_.directory = false; + } + end_ = false; + } + } + #endif + if(false == end_) + { + find_ptr_ = std::shared_ptr(new find_handle_t(handle), inner_handle_deleter()); + handle_ = handle; + } + } + + void _m_read() + { + if(handle_) + { + #if defined(NANA_WINDOWS) + if(::FindNextFile(handle_, &wfd_) != 0) + { + while(_m_ignore(wfd_.cFileName)) + { + if(::FindNextFile(handle_, &wfd_) == 0) + { + end_ = true; + return; + } + } + value_ = value_type(wfd_); + } + else + end_ = true; + #elif defined(NANA_LINUX) + struct dirent * dnt = readdir(handle_); + if(dnt) + { + while(_m_ignore(dnt->d_name)) + { + dnt = readdir(handle_); + if(dnt == 0) + { + end_ = true; + return; + } + } + struct stat fst; + if(stat((path_ + "/" + dnt->d_name).c_str(), &fst) == 0) + value_ = value_type(nana::charset(dnt->d_name), fst); + else + value_.name = nana::charset(dnt->d_name); + } + else + end_ = true; + #endif + } + } + private: + struct inner_handle_deleter + { + void operator()(find_handle_t * handle) + { + if(handle && *handle) + { + #if defined(NANA_WINDOWS) + ::FindClose(*handle); + #elif defined(NANA_LINUX) + ::closedir(*handle); + #endif + } + delete handle; + } + }; + private: + bool end_; + +#if defined(NANA_WINDOWS) + WIN32_FIND_DATA wfd_; + nana::string path_; +#elif defined(NANA_LINUX) + std::string path_; +#endif + std::shared_ptr find_ptr_; + + find_handle_t handle_; + value_type value_; + }; + + //template + inline bool operator==(const directory_iterator/**/ & x, const directory_iterator/**/ & y) + { + return x.equal(y); + } + + //template + inline bool operator!=(const directory_iterator/**/ & x, const directory_iterator/**/ & y) + { + return !x.equal(y); + } + + //using directory_iterator = directory_iterator ; +}//end namespace filesystem +}//end namespace nana + +#endif From 0b63ca51f7153270b2df657aea9013f9074656c8 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 21 May 2015 15:43:14 +0200 Subject: [PATCH 03/12] mimic std directory_iterator and directory_entry --- include/nana/filesystem/filesystem.hpp | 44 ++++++++++++++++---------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index bfdd1a71..f71504b7 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -24,7 +24,7 @@ // http://www.boost.org/doc/libs/1_58_0/libs/filesystem/doc/index.htm --- // http://www.boost.org/doc/libs/1_34_0/libs/filesystem/doc/index.htm // http://www.boost.org/doc/libs/1_58_0/boost/filesystem.hpp - +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x --- Table 1.4. g++ C++ Technical Specifications Implementation Status #ifndef NANA_FILESYSTEM_HPP #define NANA_FILESYSTEM_HPP @@ -49,16 +49,18 @@ namespace nana { namespace filesystem { - struct fileinfo - { - fileinfo(); -#ifdef NANA_WINDOWS - fileinfo(const WIN32_FIND_DATA& wfd); -#elif NANA_LINUX - fileinfo(const nana::string& filename, const struct stat &); -#endif - nana::string name; + using path = nana::string; + struct directory_entry + { + directory_entry(); + directory_entry(const nana::string& filename, bool is_directory, unsigned long size) + :name{filename}, size{size}, directory{is_directory} + {} + const path& path() const noexcept{return name;} + //operator const path&() const noexcept; + + nana::string name; unsigned long size; bool directory; }; @@ -66,10 +68,10 @@ namespace filesystem /// an iterator for a sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator //template - class directory_iterator :public std::iterator + class directory_iterator :public std::iterator { public: - typedef fileinfo value_type; + using value_type = directory_entry ; directory_iterator():end_(true), handle_(nullptr){} @@ -135,7 +137,11 @@ namespace filesystem return; } } - value_ = value_type(wfd_); + + value_ = value_type(wfd_.cFileName, + (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY, + wfd_.nFileSizeLow); + #elif defined(NANA_LINUX) path_ = nana::charset(file_path); if(path_.size() && (path_[path_.size() - 1] != '/')) @@ -160,7 +166,7 @@ namespace filesystem struct stat fst; if(stat((path_ + dnt->d_name).c_str(), &fst) == 0) { - value_ = value_type(nana::charset(dnt->d_name), fst); + value_ = value_type(nana::charset(dnt->d_name), 0 != S_ISDIR(fst.st_mode), fst.st_size); } else { @@ -194,7 +200,9 @@ namespace filesystem return; } } - value_ = value_type(wfd_); + value_ = value_type(wfd_.cFileName, + (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY, + wfd_.nFileSizeLow); } else end_ = true; @@ -213,7 +221,9 @@ namespace filesystem } struct stat fst; if(stat((path_ + "/" + dnt->d_name).c_str(), &fst) == 0) - value_ = value_type(nana::charset(dnt->d_name), fst); + value_ = value_type(wfd_.cFileName, + (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY, + wfd_.nFileSizeLow); else value_.name = nana::charset(dnt->d_name); } @@ -265,7 +275,7 @@ namespace filesystem return !x.equal(y); } - //using directory_iterator = directory_iterator ; + //using directory_iterator = directory_iterator ; }//end namespace filesystem }//end namespace nana From 02961f16737594f8620dcd4f869288c3fabb115f Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 21 May 2015 22:06:14 +0200 Subject: [PATCH 04/12] add file_type (from type), bring all from fs_utility and mimic path, and directory_entry --- build/vc2013/nana.vcxproj | 1 + build/vc2013/nana.vcxproj.filters | 3 + include/nana/filesystem/filesystem.hpp | 81 ++++- source/filesystem/filesystem.cpp | 442 +++++++++++++++++++++++++ 4 files changed, 517 insertions(+), 10 deletions(-) create mode 100644 source/filesystem/filesystem.cpp diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj index 5f16d613..9547b689 100644 --- a/build/vc2013/nana.vcxproj +++ b/build/vc2013/nana.vcxproj @@ -177,6 +177,7 @@ + diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters index 1b098164..cb51dab8 100644 --- a/build/vc2013/nana.vcxproj.filters +++ b/build/vc2013/nana.vcxproj.filters @@ -300,6 +300,9 @@ Source Files\nana\gui\widgets + + Source Files\nana\filesystem + diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index f71504b7..1f387006 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -49,20 +49,81 @@ namespace nana { namespace filesystem { - using path = nana::string; + enum class file_type + { + none = 0, ///< has not been determined or an error occurred while trying to determine + not_found = -1, ///< Pseudo-type: file was not found. Is not considered an error + regular = 1, + directory = 2 , + symlink =3, ///< Symbolic link file + block =4, ///< Block special file + character= 5 , ///< Character special file + fifo = 6 , ///< FIFO or pipe file + socket =7, + unknown= 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other + }; + + enum class error { none = 0 }; + + struct attribute + { + long long bytes; + bool is_directory; + tm modified; + }; + + bool file_attrib(const nana::string& file, attribute&); + long long filesize(const nana::string& file); + + bool mkdir(const nana::string& dir, bool & if_exist); + bool modified_file_time(const nana::string& file, struct tm&); + + nana::string path_user(); + nana::string path_current(); + + bool rmfile(const nana::char_t* file); + bool rmdir(const nana::char_t* dir, bool fails_if_not_empty); + nana::string root(const nana::string& path); + + /// concerned only with lexical and syntactic aspects and does not necessarily exist in + /// external storage, and the pathname is not necessarily valid for the current operating system + /// or for a particular file system + /// A sequence of elements that identify the location of a file within a filesystem. + /// The elements are the: + /// rootname (opt), root-directory (opt), and an optional sequence of filenames. + /// The maximum number of elements in the sequence is operating system dependent. + class path + { + public: + path(); + path(const nana::string&); + + bool empty() const; + path root() const; + file_type what() const; + + nana::string name() const; + private: +#if defined(NANA_WINDOWS) + nana::string text_; +#else + std::string text_; +#endif + }; struct directory_entry { - directory_entry(); - directory_entry(const nana::string& filename, bool is_directory, unsigned long size) - :name{filename}, size{size}, directory{is_directory} - {} - const path& path() const noexcept{return name;} - //operator const path&() const noexcept; - - nana::string name; + path m_path; unsigned long size; bool directory; + + directory_entry(); + directory_entry(const nana::string& filename, bool is_directory, unsigned long size) + :m_path{filename}, size{size}, directory{is_directory} + {} + operator const path&() const noexcept; + const path& path() const noexcept{return m_path;} + }; @@ -100,7 +161,7 @@ namespace filesystem bool equal(const directory_iterator& x) const { if(end_ && (end_ == x.end_)) return true; - return (value_.name == x.value_.name); + return (value_.path().name() == x.value_.path().name()); } private: template diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp new file mode 100644 index 00000000..e79f786a --- /dev/null +++ b/source/filesystem/filesystem.cpp @@ -0,0 +1,442 @@ +/* + * A FileSystem Utility Implementation + * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * @file: nana/filesystem/filesystem.cpp + * @description: + * provide some interface for file managment + */ + +#include +#include +#if defined(NANA_WINDOWS) + #include + + #if defined(NANA_MINGW) + #ifndef _WIN32_IE + #define _WIN32_IE 0x0500 + #endif + #endif + + #include + #include +#elif defined(NANA_LINUX) + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif + +namespace nana +{ +namespace filesystem +{ +//Because of No wide character version of POSIX +#if defined(NANA_LINUX) + typedef std::string string_t; + const char* splstr = "/\\"; +#else + typedef nana::string string_t; + const nana::char_t* splstr = STR("/\\"); +#endif + //class path + path::path(){} + + path::path(const nana::string& text) +#if defined(NANA_WINDOWS) + :text_(text) + { +#else + :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); + } + + bool path::empty() const + { +#if defined(NANA_WINDOWS) + return (::GetFileAttributes(text_.c_str()) == INVALID_FILE_ATTRIBUTES); +#elif defined(NANA_LINUX) + 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 + { +#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; +#elif defined(NANA_LINUX) + struct stat sta; + if(-1 == ::stat(text_.c_str(), &sta)) + return file_type:: not_found ; //?? + + 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); +#if defined(NANA_WINDOWS) + 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.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.bytes = li.QuadPart; + attr.is_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; + } + + long long filesize(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 mkdir(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(); + } + + nana::string path_current() + { +#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 nana From 59f0ace35397c49bd47d7b8f1912cf96d505e129 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 22 May 2015 00:19:13 +0200 Subject: [PATCH 05/12] mimic enum class perms , more adaption --- include/nana/filesystem/filesystem.hpp | 165 +++++++++++++++++++++---- source/filesystem/filesystem.cpp | 12 +- 2 files changed, 144 insertions(+), 33 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 1f387006..3b8f3dd7 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -30,6 +30,7 @@ #define NANA_FILESYSTEM_HPP #include #include +#include #include @@ -63,27 +64,62 @@ namespace filesystem unknown= 8 ///< The file does exist, but is of an operating system dependent type not covered by any of the other }; + enum class perms + { + none =0, ///< There are no permissions set for the file. + unknown = 0xFFFF ///< not known, such as when a file_status object is created without specifying the permissions + }; + //enum class copy_options; + //enum class directory_options; + + // class filesystem_error; enum class error { none = 0 }; - struct attribute + struct attribute // deprecate ?? { - long long bytes; - bool is_directory; - tm modified; + uintmax_t size {}; + bool directory{}; + tm modified {}; + + attribute() {} ; + attribute( uintmax_t size, bool is_directory) :size{size}, directory{is_directory} {} }; - bool file_attrib(const nana::string& file, attribute&); - long long filesize(const nana::string& file); + struct space_info + { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; + }; + using file_time_type = std::chrono::time_point< std::chrono::system_clock>;// trivial-clock> ; - bool mkdir(const nana::string& dir, bool & if_exist); - bool modified_file_time(const nana::string& file, struct tm&); + class file_status + { + file_type m_ft = file_type::none; + perms m_prms = perms::unknown; - nana::string path_user(); - nana::string path_current(); + public: + explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown) noexcept + :m_ft{ft}, m_prms{prms} + {} - bool rmfile(const nana::char_t* file); - bool rmdir(const nana::char_t* dir, bool fails_if_not_empty); - nana::string root(const nana::string& path); + file_status(const file_status& fs) noexcept: m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default; + file_status(file_status&& fs) noexcept: m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default; + + ~file_status(){}; + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&fs) noexcept // = default; + { + m_ft=fs.m_ft; m_prms = fs.m_prms; + return *this; + } + // observers + file_type type() const noexcept{ return m_ft;} + perms permissions() const noexcept{ return m_prms;} + // modifiers + void type (file_type ft) noexcept { m_ft=ft ;} + void permissions(perms prms) noexcept { m_prms = prms; } + }; /// concerned only with lexical and syntactic aspects and does not necessarily exist in /// external storage, and the pathname is not necessarily valid for the current operating system @@ -114,33 +150,40 @@ namespace filesystem struct directory_entry { path m_path; - unsigned long size; - bool directory; + + attribute attr{}; + //file_status m_status; directory_entry(); - directory_entry(const nana::string& filename, bool is_directory, unsigned long size) - :m_path{filename}, size{size}, directory{is_directory} + directory_entry(const nana::string& filename, bool is_directory, uintmax_t size) + :m_path{filename}, attr{size, is_directory} {} - operator const path&() const noexcept; + + void assign (const path& p){ m_path=p;} + void replace_filename(const path& p){ m_path=p;} + + //file_status status() const; + + operator const path&() const noexcept{return m_path;}; const path& path() const noexcept{return m_path;} }; - /// an iterator for a sequence of directory_entry elements representing the files in a directory, not an recursive_directory_iterator //template class directory_iterator :public std::iterator { public: using value_type = directory_entry ; + typedef ptrdiff_t difference_type; + typedef const directory_entry* pointer; + typedef const directory_entry& reference; + typedef std::input_iterator_tag iterator_category; directory_iterator():end_(true), handle_(nullptr){} - directory_iterator(const nana::string& file_path) - :end_(false), handle_(nullptr) - { - _m_prepare(file_path); - } + directory_iterator(const nana::string& file_path) { _m_prepare(file_path); } + directory_iterator(const path& file_path) { _m_prepare(file_path.name()); } const value_type& operator*() const { return value_; } @@ -310,7 +353,7 @@ namespace filesystem } }; private: - bool end_; + bool end_{false}; #if defined(NANA_WINDOWS) WIN32_FIND_DATA wfd_; @@ -320,10 +363,19 @@ namespace filesystem #endif std::shared_ptr find_ptr_; - find_handle_t handle_; + find_handle_t handle_{nullptr}; value_type value_; }; + // enable directory_iterator range-based for statements + directory_iterator begin(directory_iterator iter) noexcept { return iter; } + directory_iterator end(const directory_iterator&) noexcept { return {}; } + + //class recursive_directory_iterator; + //// enable recursive_directory_iterator range-based for statements + //recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; + //recursive_directory_iterator end(const recursive_directory_iterator&) noexcept; + //template inline bool operator==(const directory_iterator/**/ & x, const directory_iterator/**/ & y) { @@ -336,7 +388,66 @@ namespace filesystem return !x.equal(y); } - //using directory_iterator = directory_iterator ; + + // file_status status(const path& p); + bool file_attrib(const nana::string& file, attribute&); + + bool is_directory(file_status s) noexcept{ return s.type() == file_type::directory ;} + bool is_directory(const path& p){return directory_iterator(p.name())->attr.directory; } + //bool is_directory(const path& p, error_code& ec) noexcept; + + //bool is_regular_file(file_status s) noexcept; + + bool is_empty(const path& p) + { + directory_iterator d(p) ; + return d->attr.directory ? d == directory_iterator() + : d->attr.size == 0; + } + //bool is_empty(const path& p, error_code& ec) noexcept; + + uintmax_t file_size(const nana::string& file); // deprecate? + uintmax_t file_size(const path& p){return file_size(p.name());} + //uintmax_t file_size(const path& p, error_code& ec) noexcept; + //long long filesize(const nana::string& file); + + + bool create_directories(const path& p); + //bool create_directories(const path& p, error_code& ec) noexcept; + bool create_directory(const path& p); + //bool create_directory(const path& p, error_code& ec) noexcept; + bool create_directory(const path& p, const path& attributes); + //bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept; + bool create_directory(const nana::string& dir, bool & if_exist); + bool create_directory(const path& p, bool & if_exist) + { + return create_directory(p.name(), if_exist); + }; + + + bool modified_file_time(const nana::string& file, struct tm&); + + + nana::string path_user(); + + + path current_path(); + //path current_path(error_code& ec); + void current_path(const path& p); + //void current_path(const path& p, error_code& ec) noexcept; + //nana::string path_current(); + + + //bool remove(const path& p); + //bool remove(const path& p, error_code& ec) noexcept; + bool rmfile(const nana::char_t* file); + + //uintmax_t remove_all(const path& p); + //uintmax_t remove_all(const path& p, error_code& ec) noexcept; + bool rmdir(const nana::char_t* dir, bool fails_if_not_empty); + nana::string root(const nana::string& path); + + }//end namespace filesystem }//end namespace nana diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index e79f786a..f578afeb 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -134,7 +134,7 @@ namespace filesystem for(auto & f : files) { - if(f.directory) + if(f.attr.directory) rm_dir_recursive(path + f.path().name()); else rmfile((path + f.path().name()).c_str()); @@ -196,8 +196,8 @@ namespace filesystem LARGE_INTEGER li; li.u.LowPart = fad.nFileSizeLow; li.u.HighPart = fad.nFileSizeHigh; - attr.bytes = li.QuadPart; - attr.is_directory = (0 != (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); + attr.size = li.QuadPart; + attr.directory = (0 != (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); detail::filetime_to_c_tm(fad.ftLastWriteTime, attr.modified); return true; } @@ -214,7 +214,7 @@ namespace filesystem return false; } - long long filesize(const nana::string& file) + uintmax_t file_size(const nana::string& file) { #if defined(NANA_WINDOWS) //Some compilation environment may fail to link to GetFileSizeEx @@ -281,7 +281,7 @@ namespace filesystem return false; } - bool mkdir(const nana::string& path, bool & if_exist) + bool create_directory(const nana::string& path, bool & if_exist) { if_exist = false; if(path.size() == 0) return false; @@ -414,7 +414,7 @@ namespace filesystem return nana::string(); } - nana::string path_current() + path current_path() { #if defined(NANA_WINDOWS) nana::char_t buf[MAX_PATH]; From f55c54f7b4ae04336f6154d67f2ec0f2156e4e1e Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 22 May 2015 23:21:01 +0200 Subject: [PATCH 06/12] 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 From 895dbcbe7db4f465b64ab9a40e3fbbd33be2aabd Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Fri, 22 May 2015 23:26:42 +0200 Subject: [PATCH 07/12] FIX: compiling with VC2015 RC --- include/nana/config.hpp | 14 +++++++++++++- source/gui/widgets/combox.cpp | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/nana/config.hpp b/include/nana/config.hpp index 77b9005c..fecf633f 100644 --- a/include/nana/config.hpp +++ b/include/nana/config.hpp @@ -13,6 +13,18 @@ #ifndef NANA_CONFIG_HPP #define NANA_CONFIG_HPP + +#if defined(_MSC_VER) +#if (_MSC_VER == 1900) + // google: break any code that tries to use codecvt or codecvt. + // google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support. + // google: Those definitions are for codecvt::id, codecvt::id and codecvt::id respectively. + // However, the codecvt::id and codecvt::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all. + // google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources. +#define STD_CODECVT_NOT_SUPPORTED +#endif // _MSC_VER == 1900 +#endif // _MSVC + //Select platform automatically #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) //Windows: @@ -35,7 +47,7 @@ #define PLATFORM_SPEC_HPP #define STD_CODECVT_NOT_SUPPORTED #else -# static_assert(false, "Only Windows and Unix are support now"); +# static_assert(false, "Only Windows and Unix are supported now"); #endif #if defined(NANA_MINGW) || defined(NANA_LINUX) diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index b1d401f5..64208c54 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -18,6 +18,8 @@ #include #include +#include + namespace nana { arg_combox::arg_combox(combox& wdg): widget(wdg) From e99783ed54d1eb2ebe76bf6497d92a25ffd6df4c Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sat, 23 May 2015 23:55:19 +0200 Subject: [PATCH 08/12] FIX: inline functions and one default constructor. Tested OK ! --- include/nana/filesystem/filesystem.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index c117a797..60a0ea12 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -139,6 +139,7 @@ namespace filesystem file_type what() const; nana::string name() const; + operator nana::string() { return name(); } private: #if defined(NANA_WINDOWS) nana::string text_; @@ -154,7 +155,7 @@ namespace filesystem attribute attr{}; //file_status m_status; - directory_entry(); + directory_entry(){} directory_entry(const nana::string& filename, bool is_directory, uintmax_t size) :m_path{filename}, attr{size, is_directory} {} @@ -368,8 +369,8 @@ namespace filesystem }; // enable directory_iterator range-based for statements - directory_iterator begin(directory_iterator iter) noexcept { return iter; } - directory_iterator end(const directory_iterator&) noexcept { return {}; } + inline directory_iterator begin(directory_iterator iter) noexcept { return iter; } + inline directory_iterator end(const directory_iterator&) noexcept { return {}; } //class recursive_directory_iterator; //// enable recursive_directory_iterator range-based for statements @@ -392,13 +393,13 @@ namespace filesystem // file_status status(const path& p); bool file_attrib(const nana::string& file, attribute&); - bool is_directory(file_status s) noexcept{ return s.type() == file_type::directory ;} - bool is_directory(const path& p){return directory_iterator(p.name())->attr.directory; } + inline bool is_directory(file_status s) noexcept{ return s.type() == file_type::directory ;} + inline bool is_directory(const path& p){return directory_iterator(p.name())->attr.directory; } //bool is_directory(const path& p, error_code& ec) noexcept; //bool is_regular_file(file_status s) noexcept; - bool is_empty(const path& p) + inline bool is_empty(const path& p) { directory_iterator d(p) ; return d->attr.directory ? d == directory_iterator() @@ -407,7 +408,7 @@ namespace filesystem //bool is_empty(const path& p, error_code& ec) noexcept; uintmax_t file_size(const nana::string& file); // deprecate? - uintmax_t file_size(const path& p){return file_size(p.name());} + inline uintmax_t file_size(const path& p){return file_size(p.name());} //uintmax_t file_size(const path& p, error_code& ec) noexcept; //long long filesize(const nana::string& file); @@ -419,7 +420,7 @@ namespace filesystem bool create_directory(const path& p, const path& attributes); //bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept; bool create_directory(const nana::string& dir, bool & if_exist); - bool create_directory(const path& p, bool & if_exist) + inline bool create_directory(const path& p, bool & if_exist) { return create_directory(p.name(), if_exist); }; From 888e65aa842acdf20aca08f4a666eb03913961f7 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 24 May 2015 00:46:59 +0200 Subject: [PATCH 09/12] the linker don't like my inlines --- include/nana/filesystem/filesystem.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 60a0ea12..35de2a94 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -9,7 +9,10 @@ * @file: stdex/filesystem/filesystem.hpp * @description: * file_iterator is a toolkit for applying each file and directory in a - * specified path. + * specified path. + * Modiffied by Ariel Vina-Rodriguez: + * Now mimic std::experimental::filesystem::v1 (boost v3) + * and need VC2015 or a C++11 compiler. With a few correction will be compiler by VC2013 */ // http://en.cppreference.com/w/cpp/experimental/fs @@ -207,6 +210,12 @@ namespace filesystem if(end_ && (end_ == x.end_)) return true; return (value_.path().name() == x.value_.path().name()); } + + + // enable directory_iterator range-based for statements + directory_iterator begin( ) noexcept { return *this; } + directory_iterator end( ) noexcept { return {}; } + private: template static bool _m_ignore(const Char * p) @@ -368,9 +377,6 @@ namespace filesystem value_type value_; }; - // enable directory_iterator range-based for statements - inline directory_iterator begin(directory_iterator iter) noexcept { return iter; } - inline directory_iterator end(const directory_iterator&) noexcept { return {}; } //class recursive_directory_iterator; //// enable recursive_directory_iterator range-based for statements @@ -407,7 +413,7 @@ namespace filesystem } //bool is_empty(const path& p, error_code& ec) noexcept; - uintmax_t file_size(const nana::string& file); // deprecate? + uintmax_t file_size(const nana::string& file); // deprecate? inline uintmax_t file_size(const path& p){return file_size(p.name());} //uintmax_t file_size(const path& p, error_code& ec) noexcept; //long long filesize(const nana::string& file); From a42931830f05d7239a39071d7aa7152e2cf60cdb Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 24 May 2015 02:00:06 +0200 Subject: [PATCH 10/12] mimic path.filename() --- include/nana/filesystem/filesystem.hpp | 22 +++++++++++----------- source/filesystem/filesystem.cpp | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 35de2a94..790968ca 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -141,8 +141,8 @@ namespace filesystem path root() const; file_type what() const; - nana::string name() const; - operator nana::string() { return name(); } + nana::string filename() const; + operator nana::string() { return filename(); } private: #if defined(NANA_WINDOWS) nana::string text_; @@ -159,8 +159,8 @@ namespace filesystem //file_status m_status; directory_entry(){} - directory_entry(const nana::string& filename, bool is_directory, uintmax_t size) - :m_path{filename}, attr{size, is_directory} + directory_entry(const nana::string& filename_, bool is_directory, uintmax_t size) + :m_path{filename_}, attr{size, is_directory} {} void assign (const path& p){ m_path=p;} @@ -187,7 +187,7 @@ namespace filesystem directory_iterator():end_(true), handle_(nullptr){} directory_iterator(const nana::string& file_path) { _m_prepare(file_path); } - directory_iterator(const path& file_path) { _m_prepare(file_path.name()); } + directory_iterator(const path& file_path) { _m_prepare(file_path.filename()); } const value_type& operator*() const { return value_; } @@ -208,7 +208,7 @@ namespace filesystem bool equal(const directory_iterator& x) const { if(end_ && (end_ == x.end_)) return true; - return (value_.path().name() == x.value_.path().name()); + return (value_.path().filename() == x.value_.path().filename()); } @@ -284,7 +284,7 @@ namespace filesystem } else { - value_.name = nana::charset(dnt->d_name); + value_.m_path = nana::charset(dnt->d_name); value_.size = 0; value_.directory = false; } @@ -339,7 +339,7 @@ namespace filesystem (FILE_ATTRIBUTE_DIRECTORY & wfd_.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY, wfd_.nFileSizeLow); else - value_.name = nana::charset(dnt->d_name); + value_.m_path = nana::charset(dnt->d_name); } else end_ = true; @@ -400,7 +400,7 @@ namespace filesystem bool file_attrib(const nana::string& file, attribute&); inline bool is_directory(file_status s) noexcept{ return s.type() == file_type::directory ;} - inline bool is_directory(const path& p){return directory_iterator(p.name())->attr.directory; } + inline bool is_directory(const path& p){return directory_iterator(p.filename())->attr.directory; } //bool is_directory(const path& p, error_code& ec) noexcept; //bool is_regular_file(file_status s) noexcept; @@ -414,7 +414,7 @@ namespace filesystem //bool is_empty(const path& p, error_code& ec) noexcept; uintmax_t file_size(const nana::string& file); // deprecate? - inline uintmax_t file_size(const path& p){return file_size(p.name());} + inline uintmax_t file_size(const path& p){return file_size(p.filename());} //uintmax_t file_size(const path& p, error_code& ec) noexcept; //long long filesize(const nana::string& file); @@ -428,7 +428,7 @@ namespace filesystem bool create_directory(const nana::string& dir, bool & if_exist); inline bool create_directory(const path& p, bool & if_exist) { - return create_directory(p.name(), if_exist); + return create_directory(p.filename(), if_exist); }; diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index 07d297f3..4c6e8d22 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -110,7 +110,7 @@ namespace nana { #endif } - nana::string path::name() const + nana::string path::filename() const { string_t::size_type pos = text_.find_last_of(splstr); #if defined(NANA_WINDOWS) @@ -136,9 +136,9 @@ namespace nana { for (auto & f : files) { if (f.attr.directory) - rm_dir_recursive(path + f.path().name()); + rm_dir_recursive(path + f.path().filename()); else - rmfile((path + f.path().name()).c_str()); + rmfile((path + f.path().filename()).c_str()); } return rmdir(dir.c_str(), true); From 9fbabadd7828316b70126f68e045bc3b0835ee68 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Sun, 24 May 2015 03:12:02 +0200 Subject: [PATCH 11/12] better mimic? --- include/nana/filesystem/filesystem.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 790968ca..658579fd 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -142,11 +142,17 @@ namespace filesystem file_type what() const; nana::string filename() const; - operator nana::string() { return filename(); } - private: #if defined(NANA_WINDOWS) + public: + nana::string to_string() const { return text_; } + operator nana::string() const { return text_; } + private: nana::string text_; #else + public: + std::string to_string() const { return text_; } + operator std::string() const { return text_; } + private: std::string text_; #endif }; @@ -187,7 +193,7 @@ namespace filesystem directory_iterator():end_(true), handle_(nullptr){} directory_iterator(const nana::string& file_path) { _m_prepare(file_path); } - directory_iterator(const path& file_path) { _m_prepare(file_path.filename()); } + //directory_iterator(const path& file_path) { _m_prepare(file_path.filename()); } const value_type& operator*() const { return value_; } @@ -400,7 +406,8 @@ namespace filesystem bool file_attrib(const nana::string& file, attribute&); inline bool is_directory(file_status s) noexcept{ return s.type() == file_type::directory ;} - inline bool is_directory(const path& p){return directory_iterator(p.filename())->attr.directory; } + inline bool is_directory(const path& p) { return directory_iterator{ p }->attr.directory; }//works?? + inline bool is_directory(const directory_entry& d) { return d.attr.directory; } //bool is_directory(const path& p, error_code& ec) noexcept; //bool is_regular_file(file_status s) noexcept; From 42819c64c21dd164b564093237f9f519be7dc228 Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Thu, 28 May 2015 16:43:14 +0200 Subject: [PATCH 12/12] eliminate noexept from our filesystem because a compiler without filesystem is not C++11 complete anyway We will go with noexeot when we will have std::filesystem... --- include/nana/config.hpp | 23 +++++++++++++-------- include/nana/filesystem/filesystem.hpp | 28 +++++++++++++------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/include/nana/config.hpp b/include/nana/config.hpp index fecf633f..58d1ffad 100644 --- a/include/nana/config.hpp +++ b/include/nana/config.hpp @@ -15,14 +15,21 @@ #if defined(_MSC_VER) -#if (_MSC_VER == 1900) - // google: break any code that tries to use codecvt or codecvt. - // google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support. - // google: Those definitions are for codecvt::id, codecvt::id and codecvt::id respectively. - // However, the codecvt::id and codecvt::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all. - // google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources. -#define STD_CODECVT_NOT_SUPPORTED -#endif // _MSC_VER == 1900 + #define _SCL_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_DEPRECATE + #pragma warning(disable : 4996) + #if (_MSC_VER < 1900) + // is this a good idea? + #define NOT_IMPLEMENTED_KEYWORD_noexcept + #endif // _MSC_VER < 1900 + #if (_MSC_VER == 1900) + // google: break any code that tries to use codecvt or codecvt. + // google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support. + // google: Those definitions are for codecvt::id, codecvt::id and codecvt::id respectively. + // However, the codecvt::id and codecvt::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all. + // google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources. + #define STD_CODECVT_NOT_SUPPORTED + #endif // _MSC_VER == 1900 #endif // _MSVC //Select platform automatically diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 658579fd..b00760d2 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -102,26 +102,26 @@ namespace filesystem perms m_prms = perms::unknown; public: - explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown) noexcept + explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown) :m_ft{ft}, m_prms{prms} {} - file_status(const file_status& fs) noexcept: m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default; - file_status(file_status&& fs) noexcept: m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default; + file_status(const file_status& fs) : m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default; + file_status(file_status&& fs) : m_ft{fs.m_ft}, m_prms{fs.m_prms}{} // = default; ~file_status(){}; - file_status& operator=(const file_status&) noexcept = default; - file_status& operator=(file_status&&fs) noexcept // = default; + file_status& operator=(const file_status&) = default; + file_status& operator=(file_status&&fs) // = default; { m_ft=fs.m_ft; m_prms = fs.m_prms; return *this; } // observers - file_type type() const noexcept{ return m_ft;} - perms permissions() const noexcept{ return m_prms;} + file_type type() const { return m_ft;} + perms permissions() const { return m_prms;} // modifiers - void type (file_type ft) noexcept { m_ft=ft ;} - void permissions(perms prms) noexcept { m_prms = prms; } + void type (file_type ft) { m_ft=ft ;} + void permissions(perms prms) { m_prms = prms; } }; /// concerned only with lexical and syntactic aspects and does not necessarily exist in @@ -174,8 +174,8 @@ namespace filesystem //file_status status() const; - operator const path&() const noexcept{return m_path;}; - const path& path() const noexcept{return m_path;} + operator const path&() const {return m_path;}; + const path& path() const {return m_path;} }; @@ -219,8 +219,8 @@ namespace filesystem // enable directory_iterator range-based for statements - directory_iterator begin( ) noexcept { return *this; } - directory_iterator end( ) noexcept { return {}; } + directory_iterator begin( ) { return *this; } + directory_iterator end( ) { return {}; } private: template @@ -405,7 +405,7 @@ namespace filesystem // file_status status(const path& p); bool file_attrib(const nana::string& file, attribute&); - inline bool is_directory(file_status s) noexcept{ return s.type() == file_type::directory ;} + inline bool is_directory(file_status s) { return s.type() == file_type::directory ;} inline bool is_directory(const path& p) { return directory_iterator{ p }->attr.directory; }//works?? inline bool is_directory(const directory_entry& d) { return d.attr.directory; } //bool is_directory(const path& p, error_code& ec) noexcept;