diff --git a/.github/workflows/of.yml b/.github/workflows/of.yml index 350ca11b2d7..3c03d0b507f 100644 --- a/.github/workflows/of.yml +++ b/.github/workflows/of.yml @@ -109,6 +109,9 @@ jobs: - name: Build run: ./scripts/ci/msys2/build.sh + +# - name: Allexamples (not quite fonctional due to relative paths +# run: ./scripts/msys2/buildAllExamples.sh ./examples # - name: Run tests # run: ./scripts/ci/msys2/run_tests.sh diff --git a/addons/ofxAssimpModelLoader/src/ofxAssimpModelLoader.cpp b/addons/ofxAssimpModelLoader/src/ofxAssimpModelLoader.cpp index 913e344aff5..3b0198f6f45 100644 --- a/addons/ofxAssimpModelLoader/src/ofxAssimpModelLoader.cpp +++ b/addons/ofxAssimpModelLoader/src/ofxAssimpModelLoader.cpp @@ -57,7 +57,7 @@ bool ofxAssimpModelLoader::loadModel(ofBuffer & buffer, bool optimize, const cha //------------------------------------------ bool ofxAssimpModelLoader::load(const of::filesystem::path & fileName, int assimpOptimizeFlags){ file = ofToDataPath(fileName); - if (!of::filesystem::exists(file)) { + if (!std::filesystem::exists(file)) { ofLogVerbose("ofxAssimpModelLoader") << "load(): model does not exist: " << fileName ; return false; } diff --git a/addons/ofxSvg/src/ofxSvg.cpp b/addons/ofxSvg/src/ofxSvg.cpp index bbbf54024f1..d7991283f42 100644 --- a/addons/ofxSvg/src/ofxSvg.cpp +++ b/addons/ofxSvg/src/ofxSvg.cpp @@ -28,8 +28,8 @@ ofPath & ofxSvg::getPathAt(int n) { } void ofxSvg::load(const of::filesystem::path & fileName) { - of::filesystem::path file = ofToDataPath(fileName); - if (!of::filesystem::exists(file)) { + auto file = ofToDataPath(fileName); + if (!std::filesystem::exists(file)) { ofLogError("ofxSVG") << "load(): path does not exist: " << file ; return; } diff --git a/libs/openFrameworks/gl/ofShader.cpp b/libs/openFrameworks/gl/ofShader.cpp index b4df3358905..38f4731b0b4 100644 --- a/libs/openFrameworks/gl/ofShader.cpp +++ b/libs/openFrameworks/gl/ofShader.cpp @@ -497,7 +497,7 @@ string ofShader::parseForIncludes(const string & source, vector // TODO: move to ofMain.h? +#define OF_USING_STD_FS 1 // TODO: remove usage of this #define which is now (C++17) always true - -// If you are building with c++17 or newer std filesystem will be enabled by default -#if __cplusplus >= 201500 -// #pragma message ( "__cplusplus >= 201500 " ) - #define OF_HAS_CPP17 - #if __cplusplus < 201703L - // #pragma message ( "__cplusplus < 201703L" ) - #define OF_USE_EXPERIMENTAL_FS - #endif -#else - #undef OF_HAS_CPP17 +#if defined(TARGET_WIN32) + #define OF_ENABLE_TOLERANT_NARROW_PATH_CONVERSION 1 // to enable the feature #endif - -#ifndef OF_USING_STD_FS - #if defined(OF_HAS_CPP17) - #define OF_USING_STD_FS - #else - #undef OF_USING_STD_FS - #endif -#endif - -// Some projects will specify OF_USING_STD_FS even if the compiler isn't newer than 201703L -// This may be okay but we need to test for the way C++17 is including the filesystem - -#if defined(OF_USING_STD_FS) && !defined(OF_USE_EXPERIMENTAL_FS) - #if defined(__cpp_lib_filesystem) - // #pragma message ( "ok __cpp_lib_filesystem" ) - #undef OF_USE_EXPERIMENTAL_FS - #elif defined(__cpp_lib_experimental_filesystem) - // #pragma message ( "ok __cpp_lib_experimental_filesystem" ) - #define OF_USE_EXPERIMENTAL_FS - #elif !defined(__has_include) - // #pragma message ( "not __has_include so we add OF_USE_EXPERIMENTAL_FS? seems wrong" ) - #define OF_USE_EXPERIMENTAL_FS - #elif __has_include() - // If we're compiling on Visual Studio and are not compiling with C++17, we need to use experimental - #ifdef _MSC_VER - - // Check and include header that defines "_HAS_CXX17" - #if __has_include() - #include - - // Check for enabled C++17 support - #if defined(_HAS_CXX17) && _HAS_CXX17 - // We're using C++17, so let's use the normal version - #undef OF_USE_EXPERIMENTAL_FS - #endif - #endif - - // If the macro isn't defined yet, that means any of the other VS specific checks failed, so we need to use experimental - #ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL - #define OF_USE_EXPERIMENTAL_FS - #endif - - // Not on Visual Studio. Let's use the normal version - #else // #ifdef _MSC_VER - #undef OF_USE_EXPERIMENTAL_FS - #endif - #else - #undef OF_USE_EXPERIMENTAL_FS - #endif -#endif - - -#if defined(OF_USE_EXPERIMENTAL_FS) - // C++17 experimental fs support - #include - namespace std { - namespace experimental{ - namespace filesystem { - using path = v1::path; - } - } - } - - namespace of { - namespace filesystem = std::experimental::filesystem; - } +#if defined(OF_ENABLE_TOLERANT_NARROW_PATH_CONVERSION) + #include "ofFilesystemPath.h" #else - #include - namespace of { - namespace filesystem = std::filesystem; - } + namespace of::filesystem { using path = std::filesystem::path; } #endif diff --git a/libs/openFrameworks/utils/ofFileUtils.cpp b/libs/openFrameworks/utils/ofFileUtils.cpp index f699f783018..cc07ed5c2b5 100644 --- a/libs/openFrameworks/utils/ofFileUtils.cpp +++ b/libs/openFrameworks/utils/ofFileUtils.cpp @@ -13,7 +13,7 @@ #include /* PATH_MAX */ #endif -namespace fs = of::filesystem; +//namespace fs = std::filesystem; using std::string; using std::vector; @@ -26,18 +26,22 @@ namespace{ bool enableDataPath = true; //-------------------------------------------------- - fs::path defaultDataPath(){ + of::filesystem::path defaultDataPath(){ #if defined TARGET_OSX try { - return fs::canonical(ofFilePath::getCurrentExeDirFS() / "../../../data/"); + auto rez = std::filesystem::canonical(ofFilePath::getCurrentExeDirFS()) / "../../../data/"; + ofLogNotice("CSANON") << rez; + return rez; } catch(...) { - return ofFilePath::getCurrentExeDirFS() / "../../../data/"; + auto rez = ofFilePath::getCurrentExeDirFS() / "../../../data/"; + ofLogNotice("non-CSANON") << rez; + return rez; } #elif defined TARGET_ANDROID return string("sdcard/"); #else try { - return fs::canonical(ofFilePath::getCurrentExeDirFS() / "data/").make_preferred(); + return std::filesystem::canonical(ofFilePath::getCurrentExeDirFS() / "data/").make_preferred(); } catch(...) { return (ofFilePath::getCurrentExeDirFS() / "data/"); } @@ -45,14 +49,14 @@ namespace{ } //-------------------------------------------------- - fs::path & defaultWorkingDirectory() { - static auto * defaultWorkingDirectory = new fs::path(ofFilePath::getCurrentExeDirFS()); + of::filesystem::path & defaultWorkingDirectory() { + static auto * defaultWorkingDirectory = new of::filesystem::path(ofFilePath::getCurrentExeDirFS()); return * defaultWorkingDirectory; } //-------------------------------------------------- - fs::path & dataPathRoot() { - static auto * dataPathRoot = new fs::path(defaultDataPath()); + of::filesystem::path & dataPathRoot() { + static auto * dataPathRoot = new of::filesystem::path(defaultDataPath()); return *dataPathRoot; } } @@ -61,7 +65,7 @@ namespace of{ namespace priv{ void initfileutils() { // FIXME: Why absolute? - defaultWorkingDirectory() = fs::absolute(fs::current_path()); + defaultWorkingDirectory() = std::filesystem::absolute(std::filesystem::current_path()); } } } @@ -451,13 +455,13 @@ istream & operator>>(istream & istr, ofBuffer & buf){ } //-------------------------------------------------- -ofBuffer ofBufferFromFile(const fs::path & path, bool binary){ +ofBuffer ofBufferFromFile(const of::filesystem::path & path, bool binary){ ofFile f(path,ofFile::ReadOnly, binary); return ofBuffer(f); } //-------------------------------------------------- -bool ofBufferToFile(const fs::path & path, const ofBuffer& buffer, bool binary){ +bool ofBufferToFile(const of::filesystem::path & path, const ofBuffer& buffer, bool binary){ ofFile f(path, ofFile::WriteOnly, binary); return buffer.writeTo(f); } @@ -474,7 +478,7 @@ ofFile::ofFile() ,binary(true){ } -ofFile::ofFile(const fs::path & path, Mode mode, bool binary) +ofFile::ofFile(const of::filesystem::path & path, Mode mode, bool binary) :mode(mode) ,binary(true){ open(path, mode, binary); @@ -556,14 +560,14 @@ bool ofFile::openStream(Mode _mode, bool _binary){ } //------------------------------------------------------------------------------------------------------------ -bool ofFile::open(const fs::path & _path, Mode _mode, bool binary){ +bool ofFile::open(const of::filesystem::path & _path, Mode _mode, bool binary){ close(); myFile = ofToDataPathFS(_path); return openStream(_mode, binary); } //------------------------------------------------------------------------------------------------------------ -bool ofFile::openFromCWD(const fs::path & _path, Mode _mode, bool binary){ +bool ofFile::openFromCWD(const of::filesystem::path & _path, Mode _mode, bool binary){ close(); myFile = _path; return openStream(_mode, binary); @@ -589,7 +593,7 @@ bool ofFile::isWriteMode(){ //------------------------------------------------------------------------------------------------------------- void ofFile::close(){ - myFile = fs::path(); + myFile = of::filesystem::path(); if(mode!=Reference) fstream::close(); } @@ -599,7 +603,7 @@ bool ofFile::create(){ } //------------------------------------------------------------------------------------------------------------ -bool ofFile::create(const fs::path & path){ +bool ofFile::create(const of::filesystem::path & path){ bool success = false; auto oldmode = this->mode; @@ -616,7 +620,7 @@ bool ofFile::create(const fs::path & path){ //------------------------------------------------------------------------------------------------------------ ofBuffer ofFile::readToBuffer(){ - if(myFile.empty() || !fs::exists(myFile)){ + if(myFile.empty() || !std::filesystem::exists(myFile)){ return ofBuffer(); } @@ -644,17 +648,17 @@ bool ofFile::exists() const { if(path().empty()){ return false; } - return fs::exists(myFile); + return std::filesystem::exists(myFile); } //------------------------------------------------------------------------------------------------------------ -fs::path ofFile::pathFS() const { +of::filesystem::path ofFile::pathFS() const { return myFile; } //------------------------------------------------------------------------------------------------------------ -std::string ofFile::path() const { - return ofPathToString(pathFS()); +of::filesystem::path ofFile::path() const { + return pathFS(); } //------------------------------------------------------------------------------------------------------------ @@ -687,7 +691,7 @@ std::string ofFile::getEnclosingDirectory() const { //------------------------------------------------------------------------------------------------------------ // MARK: - near future FS -std::string ofFile::getAbsolutePath() const { +of::filesystem::path ofFile::getAbsolutePath() const { return ofFilePath::getAbsolutePath(path()); } @@ -704,22 +708,22 @@ bool ofFile::canRead() const { #else struct stat info; stat(path().c_str(), &info); // Error check omitted - auto perm = fs::status(myFile).permissions(); + auto perm = std::filesystem::status(myFile).permissions(); #if defined(OF_USING_STD_FS) if(geteuid() == info.st_uid){ - return (perm & fs::perms::owner_read) != fs::perms::none; + return (perm & std::filesystem::perms::owner_read) != std::filesystem::perms::none; }else if (getegid() == info.st_gid){ - return (perm & fs::perms::group_read) != fs::perms::none; + return (perm & std::filesystem::perms::group_read) != std::filesystem::perms::none; }else{ - return (perm & fs::perms::others_read) != fs::perms::none; + return (perm & std::filesystem::perms::others_read) != std::filesystem::perms::none; } #else if(geteuid() == info.st_uid){ - return perm & fs::perms::owner_read; + return perm & std::filesystem::perms::owner_read; }else if (getegid() == info.st_gid){ - return perm & fs::perms::group_read; + return perm & std::filesystem::perms::group_read; }else{ - return perm & fs::perms::others_read; + return perm & std::filesystem::perms::others_read; } #endif #endif @@ -737,22 +741,22 @@ bool ofFile::canWrite() const { #else struct stat info; stat(path().c_str(), &info); // Error check omitted - auto perm = fs::status(myFile).permissions(); + auto perm = std::filesystem::status(myFile).permissions(); #if defined(OF_USING_STD_FS) if(geteuid() == info.st_uid){ - return (perm & fs::perms::owner_write) != fs::perms::none; + return (perm & std::filesystem::perms::owner_write) != std::filesystem::perms::none; }else if (getegid() == info.st_gid){ - return (perm & fs::perms::group_write) != fs::perms::none; + return (perm & std::filesystem::perms::group_write) != std::filesystem::perms::none; }else{ - return (perm & fs::perms::others_write) != fs::perms::none; + return (perm & std::filesystem::perms::others_write) != std::filesystem::perms::none; } #else if(geteuid() == info.st_uid){ - return perm & fs::owner_write; + return perm & std::filesystem::owner_write; }else if (getegid() == info.st_gid){ - return perm & fs::group_write; + return perm & std::filesystem::group_write; }else{ - return perm & fs::others_write; + return perm & std::filesystem::others_write; } #endif #endif @@ -765,39 +769,39 @@ bool ofFile::canExecute() const { #else struct stat info; stat(path().c_str(), &info); // Error check omitted - auto perm = fs::status(myFile).permissions(); + auto perm = std::filesystem::status(myFile).permissions(); #if defined(OF_USING_STD_FS) if(geteuid() == info.st_uid){ - return (perm & fs::perms::owner_exec) != fs::perms::none; + return (perm & std::filesystem::perms::owner_exec) != std::filesystem::perms::none; }else if (getegid() == info.st_gid){ - return (perm & fs::perms::group_exec) != fs::perms::none; + return (perm & std::filesystem::perms::group_exec) != std::filesystem::perms::none; }else{ - return (perm & fs::perms::others_exec) != fs::perms::none; + return (perm & std::filesystem::perms::others_exec) != std::filesystem::perms::none; } #else if(geteuid() == info.st_uid){ - return perm & fs::owner_exe; + return perm & std::filesystem::owner_exe; }else if (getegid() == info.st_gid){ - return perm & fs::group_exe; + return perm & std::filesystem::group_exe; }else{ - return perm & fs::others_exe; + return perm & std::filesystem::others_exe; } #endif #endif } //------------------------------------------------------------------------------------------------------------ bool ofFile::isFile() const { - return fs::is_regular_file(myFile); + return std::filesystem::is_regular_file(myFile); } //------------------------------------------------------------------------------------------------------------ bool ofFile::isLink() const { - return fs::is_symlink(myFile); + return std::filesystem::is_symlink(myFile); } //------------------------------------------------------------------------------------------------------------ bool ofFile::isDirectory() const { - return fs::is_directory(myFile); + return std::filesystem::is_directory(myFile); } //------------------------------------------------------------------------------------------------------------ @@ -806,9 +810,9 @@ bool ofFile::isDevice() const { return false; #else #if defined(OF_USING_STD_FS) - return fs::is_block_file(fs::status(myFile)); + return std::filesystem::is_block_file(std::filesystem::status(myFile)); #else - return fs::status(myFile).type() == fs::block_file; + return std::filesystem::status(myFile).type() == std::filesystem::block_file; #endif #endif } @@ -827,15 +831,15 @@ void ofFile::setWriteable(bool flag){ try{ #if !defined(OF_USING_STD_FS) || (defined(OF_USING_STD_FS) && defined(OF_USE_EXPERIMENTAL_FS)) if(flag){ - fs::permissions(myFile,fs::perms::owner_write | fs::perms::add_perms); + std::filesystem::permissions(myFile,std::filesystem::perms::owner_write | std::filesystem::perms::add_perms); }else{ - fs::permissions(myFile,fs::perms::owner_write | fs::perms::remove_perms); + std::filesystem::permissions(myFile,std::filesystem::perms::owner_write | std::filesystem::perms::remove_perms); } #else if(flag){ - fs::permissions(myFile, fs::perms::owner_write, fs::perm_options::add); + std::filesystem::permissions(myFile, std::filesystem::perms::owner_write, std::filesystem::perm_options::add); }else{ - fs::permissions(myFile, fs::perms::owner_write, fs::perm_options::remove); + std::filesystem::permissions(myFile, std::filesystem::perms::owner_write, std::filesystem::perm_options::remove); } #endif }catch(std::exception & e){ @@ -854,19 +858,19 @@ void ofFile::setReadable(bool flag){ try{ #if !defined(OF_USING_STD_FS) || (defined(OF_USING_STD_FS) && defined(OF_USE_EXPERIMENTAL_FS)) if(flag){ - fs::permissions(myFile,fs::perms::owner_read | fs::perms::add_perms); + std::filesystem::permissions(myFile,std::filesystem::perms::owner_read | std::filesystem::perms::add_perms); }else{ - fs::permissions(myFile,fs::perms::owner_read | fs::perms::remove_perms); + std::filesystem::permissions(myFile,std::filesystem::perms::owner_read | std::filesystem::perms::remove_perms); } #else if(flag){ - fs::permissions(myFile, - fs::perms::owner_read, - fs::perm_options::add); + std::filesystem::permissions(myFile, + std::filesystem::perms::owner_read, + std::filesystem::perm_options::add); }else{ - fs::permissions(myFile, - fs::perms::owner_read, - fs::perm_options::remove); + std::filesystem::permissions(myFile, + std::filesystem::perms::owner_read, + std::filesystem::perm_options::remove); } #endif }catch(std::exception & e){ @@ -880,26 +884,26 @@ void ofFile::setExecutable(bool flag){ #if defined(OF_USING_STD_FS) # if defined(OF_USE_EXPERIMENTAL_FS) if(flag){ - fs::permissions(myFile, fs::perms::owner_exec | fs::perms::add_perms); + std::filesystem::permissions(myFile, std::filesystem::perms::owner_exec | std::filesystem::perms::add_perms); } else{ - fs::permissions(myFile, fs::perms::owner_exec | fs::perms::remove_perms); + std::filesystem::permissions(myFile, std::filesystem::perms::owner_exec | std::filesystem::perms::remove_perms); } # else if(flag){ - fs::permissions(myFile, - fs::perms::owner_exec, - fs::perm_options::add); + std::filesystem::permissions(myFile, + std::filesystem::perms::owner_exec, + std::filesystem::perm_options::add); } else{ - fs::permissions(myFile, - fs::perms::owner_exec, - fs::perm_options::remove); + std::filesystem::permissions(myFile, + std::filesystem::perms::owner_exec, + std::filesystem::perm_options::remove); } # endif #else if(flag){ - fs::permissions(myFile, fs::perms::owner_exe | fs::perms::add_perms); + std::filesystem::permissions(myFile, std::filesystem::perms::owner_exe | std::filesystem::perms::add_perms); } else{ - fs::permissions(myFile, fs::perms::owner_exe | fs::perms::remove_perms); + std::filesystem::permissions(myFile, std::filesystem::perms::owner_exe | std::filesystem::perms::remove_perms); } #endif }catch(std::exception & e){ @@ -908,7 +912,7 @@ void ofFile::setExecutable(bool flag){ } //------------------------------------------------------------------------------------------------------------ -bool ofFile::copyTo(const fs::path & _path, bool bRelativeToData, bool overwrite) const{ +bool ofFile::copyTo(const of::filesystem::path & _path, bool bRelativeToData, bool overwrite) const{ auto path = _path; if(path.empty()){ @@ -955,7 +959,7 @@ bool ofFile::copyTo(const fs::path & _path, bool bRelativeToData, bool overwrite if(!destDir.exists()){ ofFilePath::createEnclosingDirectory(path, false); } - fs::copy_file(myFile,path); + std::filesystem::copy_file(myFile,path); }catch(std::exception & except){ ofLogError("ofFile") << "copyTo(): unable to copy " << path << ": " << except.what(); return false; @@ -965,7 +969,7 @@ bool ofFile::copyTo(const fs::path & _path, bool bRelativeToData, bool overwrite } //------------------------------------------------------------------------------------------------------------ -bool ofFile::moveTo(const fs::path& _path, bool bRelativeToData, bool overwrite){ +bool ofFile::moveTo(const of::filesystem::path& _path, bool bRelativeToData, bool overwrite){ auto path = _path; if(path.empty()){ @@ -1008,7 +1012,7 @@ bool ofFile::moveTo(const fs::path& _path, bool bRelativeToData, bool overwrite) if(!destDir.exists()){ ofFilePath::createEnclosingDirectory(path,false); } - fs::rename(myFile,path); + std::filesystem::rename(myFile,path); myFile = path; if(mode != ofFile::Reference){ changeMode(mode, binary); @@ -1023,7 +1027,7 @@ bool ofFile::moveTo(const fs::path& _path, bool bRelativeToData, bool overwrite) } //------------------------------------------------------------------------------------------------------------ -bool ofFile::renameTo(const fs::path& path, bool bRelativeToData, bool overwrite){ +bool ofFile::renameTo(const of::filesystem::path& path, bool bRelativeToData, bool overwrite){ return moveTo(path,bRelativeToData,overwrite); } @@ -1043,9 +1047,9 @@ bool ofFile::remove(bool recursive){ open(path(),Reference,binary); } if(recursive){ - fs::remove_all(myFile); + std::filesystem::remove_all(myFile); }else{ - fs::remove(myFile); + std::filesystem::remove(myFile); } }catch(std::exception & except){ ofLogError("ofFile") << "remove(): unable to remove " << myFile << ": " << except.what(); @@ -1058,7 +1062,7 @@ bool ofFile::remove(bool recursive){ //------------------------------------------------------------------------------------------------------------ uint64_t ofFile::getSize() const { try{ - return fs::file_size(myFile); + return std::filesystem::file_size(myFile); }catch(std::exception & except){ ofLogError("ofFile") << "getSize(): unable to get size of " << myFile << ": " << except.what(); return 0; @@ -1099,7 +1103,7 @@ bool ofFile::operator>=(const ofFile & file) const { // ofFile Static Methods //------------------------------------------------------------------------------------------------------------ -bool ofFile::copyFromTo(const fs::path& pathSrc, const fs::path& pathDst, bool bRelativeToData, bool overwrite){ +bool ofFile::copyFromTo(const of::filesystem::path& pathSrc, const of::filesystem::path& pathDst, bool bRelativeToData, bool overwrite){ ofFile tmp; if( bRelativeToData ){ tmp.open(pathSrc,ofFile::Reference); @@ -1111,7 +1115,7 @@ bool ofFile::copyFromTo(const fs::path& pathSrc, const fs::path& pathDst, bool b //be careful with slashes here - appending a slash when moving a folder will causes mad headaches //------------------------------------------------------------------------------------------------------------ -bool ofFile::moveFromTo(const fs::path& pathSrc, const fs::path& pathDst, bool bRelativeToData, bool overwrite){ +bool ofFile::moveFromTo(const of::filesystem::path& pathSrc, const of::filesystem::path& pathDst, bool bRelativeToData, bool overwrite){ ofFile tmp; if( bRelativeToData ){ tmp.open(pathSrc,ofFile::Reference); @@ -1122,7 +1126,7 @@ bool ofFile::moveFromTo(const fs::path& pathSrc, const fs::path& pathDst, bool b } //------------------------------------------------------------------------------------------------------------ -bool ofFile::doesFileExist(const fs::path & _path, bool bRelativeToData){ +bool ofFile::doesFileExist(const of::filesystem::path & _path, bool bRelativeToData){ auto path = _path; if (path.empty()) { return false; @@ -1130,11 +1134,11 @@ bool ofFile::doesFileExist(const fs::path & _path, bool bRelativeToData){ if(bRelativeToData){ path = ofToDataPath(path); } - return !path.empty() && of::filesystem::exists(path); + return !path.empty() && std::filesystem::exists(path); } //------------------------------------------------------------------------------------------------------------ -bool ofFile::removeFile(const fs::path& _path, bool bRelativeToData){ +bool ofFile::removeFile(const of::filesystem::path& _path, bool bRelativeToData){ ofFile tmp; if(bRelativeToData){ tmp.open(_path,ofFile::Reference); @@ -1157,20 +1161,20 @@ ofDirectory::ofDirectory(){ } //------------------------------------------------------------------------------------------------------------ -ofDirectory::ofDirectory(const fs::path & path){ +ofDirectory::ofDirectory(const of::filesystem::path & path){ showHidden = false; open(path); } //------------------------------------------------------------------------------------------------------------ -void ofDirectory::open(const fs::path & path){ +void ofDirectory::open(const of::filesystem::path & path){ originalDirectory = ofFilePath::getPathForDirectoryFS(path); files.clear(); myDir = ofToDataPathFS(originalDirectory); } //------------------------------------------------------------------------------------------------------------ -void ofDirectory::openFromCWD(const fs::path & path){ +void ofDirectory::openFromCWD(const of::filesystem::path & path){ originalDirectory = ofFilePath::getPathForDirectoryFS(path); files.clear(); myDir = originalDirectory; @@ -1178,7 +1182,7 @@ void ofDirectory::openFromCWD(const fs::path & path){ //------------------------------------------------------------------------------------------------------------ void ofDirectory::close(){ - myDir = fs::path(); + myDir = of::filesystem::path(); } //------------------------------------------------------------------------------------------------------------ @@ -1187,9 +1191,9 @@ bool ofDirectory::create(bool recursive){ if(!myDir.empty()){ try{ if(recursive){ - fs::create_directories(myDir); + std::filesystem::create_directories(myDir); }else{ - fs::create_directory(myDir); + std::filesystem::create_directory(myDir); } } catch(std::exception & except){ @@ -1203,28 +1207,28 @@ bool ofDirectory::create(bool recursive){ //------------------------------------------------------------------------------------------------------------ bool ofDirectory::exists() const { - return (myDir == "" || fs::exists(myDir)); + return (myDir.empty() || std::filesystem::exists(myDir)); } //------------------------------------------------------------------------------------------------------------ // MARK: - near future FS -std::string ofDirectory::path() const { - return ofPathToString(myDir); +of::filesystem::path ofDirectory::path() const { + return myDir; } //------------------------------------------------------------------------------------------------------------ -fs::path ofDirectory::getAbsolutePathFS() const { +of::filesystem::path ofDirectory::getAbsolutePathFS() const { try { - return fs::canonical(fs::absolute(myDir)); + return std::filesystem::canonical(std::filesystem::absolute(myDir)); } catch(...) { - return fs::absolute(myDir); + return std::filesystem::absolute(myDir); } } // MARK: - near future FS //------------------------------------------------------------------------------------------------------------ -std::string ofDirectory::getAbsolutePath() const { - return ofPathToString(ofDirectory::getAbsolutePathFS()); +of::filesystem::path ofDirectory::getAbsolutePath() const { + return ofDirectory::getAbsolutePathFS(); } //------------------------------------------------------------------------------------------------------------ @@ -1275,22 +1279,22 @@ void ofDirectory::setShowHidden(bool showHidden){ //------------------------------------------------------------------------------------------------------------ bool ofDirectory::isDirectory() const { - return fs::is_directory(myDir); + return std::filesystem::is_directory(myDir); } //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::copyTo(const fs::path & _path, bool bRelativeToData, bool overwrite){ +bool ofDirectory::copyTo(const of::filesystem::path & _path, bool bRelativeToData, bool overwrite){ auto path = _path; if(myDir.empty()){ ofLogError("ofDirectory") << "copyTo(): source path is empty"; return false; } - if(!fs::exists(myDir)){ + if(!std::filesystem::exists(myDir)){ ofLogError("ofDirectory") << "copyTo(): source directory does not exist"; return false; } - if(!fs::is_directory(myDir)){ + if(!std::filesystem::is_directory(myDir)){ ofLogError("ofDirectory") << "copyTo(): source path is not a directory"; return false; } @@ -1314,10 +1318,10 @@ bool ofDirectory::copyTo(const fs::path & _path, bool bRelativeToData, bool over dir.create(true); // Iterate through the source directory - for(fs::directory_iterator file(myDir); file != fs::directory_iterator(); ++file){ - auto currentPath = fs::absolute(file->path()); - auto dst = fs::path(path) / currentPath.filename(); - if(fs::is_directory(currentPath)){ + for(std::filesystem::directory_iterator file(myDir); file != std::filesystem::directory_iterator(); ++file){ + auto currentPath = std::filesystem::absolute(file->path()); + auto dst = of::filesystem::path(path) / currentPath.filename(); + if(std::filesystem::is_directory(currentPath)){ ofDirectory current(currentPath); // Found directory: Recursion if(!current.copyTo(dst,false,overwrite)){ @@ -1334,7 +1338,7 @@ bool ofDirectory::copyTo(const fs::path & _path, bool bRelativeToData, bool over } //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::moveTo(const fs::path& path, bool bRelativeToData, bool overwrite){ +bool ofDirectory::moveTo(const of::filesystem::path& path, bool bRelativeToData, bool overwrite){ if(copyTo(path,bRelativeToData,overwrite)){ return remove(true); } @@ -1343,21 +1347,21 @@ bool ofDirectory::moveTo(const fs::path& path, bool bRelativeToData, bool overwr } //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::renameTo(const fs::path& path, bool bRelativeToData, bool overwrite){ +bool ofDirectory::renameTo(const of::filesystem::path& path, bool bRelativeToData, bool overwrite){ return moveTo(path, bRelativeToData, overwrite); } //------------------------------------------------------------------------------------------------------------ bool ofDirectory::remove(bool recursive){ - if(path().empty() || !fs::exists(myDir)){ + if(path().empty() || !std::filesystem::exists(myDir)){ return false; } try{ if(recursive){ - fs::remove_all(fs::canonical(myDir)); + std::filesystem::remove_all(std::filesystem::canonical(myDir)); }else{ - fs::remove(fs::canonical(myDir)); + std::filesystem::remove(std::filesystem::canonical(myDir)); } }catch(std::exception & except){ ofLogError("ofDirectory") << "remove(): unable to remove file/directory: " << except.what(); @@ -1376,7 +1380,7 @@ void ofDirectory::allowExt(const std::string& extension){ } //------------------------------------------------------------------------------------------------------------ -std::size_t ofDirectory::listDir(const fs::path & directory){ +std::size_t ofDirectory::listDir(const of::filesystem::path & directory){ open(directory); return listDir(); } @@ -1388,13 +1392,13 @@ std::size_t ofDirectory::listDir(){ ofLogError("ofDirectory") << "listDir(): directory path is empty"; return 0; } - if(!fs::exists(myDir)){ + if(!std::filesystem::exists(myDir)){ ofLogError("ofDirectory") << "listDir:() source directory does not exist: " << myDir ; return 0; } - if ( fs::exists(myDir) && fs::is_directory(myDir)){ - for (const auto & f : fs::directory_iterator{ myDir }) { + if ( std::filesystem::exists(myDir) && std::filesystem::is_directory(myDir)){ + for (const auto & f : std::filesystem::directory_iterator{ myDir }) { files.emplace_back(f.path(), ofFile::Reference); } }else{ @@ -1483,7 +1487,7 @@ static bool natural(const ofFile& a, const ofFile& b) { //------------------------------------------------------------------------------------------------------------ struct StringSort{ - fs::path path; + of::filesystem::path path; string basename; int nameInt; string stringInt; @@ -1500,8 +1504,8 @@ static bool naturalStr(const StringSort& a, const StringSort& b) { //------------------------------------------------------------------------------------------------------------ static bool byDate(const ofFile& a, const ofFile& b) { - auto ta = fs::last_write_time(a); - auto tb = fs::last_write_time(b); + auto ta = std::filesystem::last_write_time(a.getAbsolutePath()); + auto tb = std::filesystem::last_write_time(b.getAbsolutePath()); return ta < tb; } @@ -1552,7 +1556,7 @@ void ofDirectory::sort(const SortMode & mode){ files.clear(); files.reserve(sort.size()); for( auto & s : sort ){ - files.emplace_back( myDir / fs::path(s), ofFile::Reference); + files.emplace_back( myDir / of::filesystem::path(s), ofFile::Reference); } }else if(mode == ofDirectory::SORT_BY_DATE){ sortByDate(); @@ -1582,7 +1586,7 @@ int ofDirectory::numFiles(){ //------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::removeDirectory(const fs::path& _path, bool deleteIfNotEmpty, bool bRelativeToData){ +bool ofDirectory::removeDirectory(const of::filesystem::path& _path, bool deleteIfNotEmpty, bool bRelativeToData){ auto path = _path; ofFile dirToRemove; @@ -1596,7 +1600,7 @@ bool ofDirectory::removeDirectory(const fs::path& _path, bool deleteIfNotEmpty, } //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::createDirectory(const fs::path& _dirPath, bool bRelativeToData, bool recursive){ +bool ofDirectory::createDirectory(const of::filesystem::path& _dirPath, bool bRelativeToData, bool recursive){ auto dirPath = _dirPath; if(bRelativeToData){ @@ -1614,9 +1618,9 @@ bool ofDirectory::createDirectory(const fs::path& _dirPath, bool bRelativeToData bool success = false; try{ if(!recursive){ - success = fs::create_directory(dirPath); + success = std::filesystem::create_directory(dirPath); }else{ - success = fs::create_directories(dirPath); + success = std::filesystem::create_directories(dirPath); } } catch(std::exception & except){ ofLogError("ofDirectory") << "createDirectory(): couldn't create directory " << dirPath << ": " << except.what(); @@ -1630,13 +1634,13 @@ bool ofDirectory::createDirectory(const fs::path& _dirPath, bool bRelativeToData } //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::doesDirectoryExist(const fs::path& _dirPath, bool bRelativeToData){ +bool ofDirectory::doesDirectoryExist(const of::filesystem::path& _dirPath, bool bRelativeToData){ auto dirPath = _dirPath; try { if (bRelativeToData) { dirPath = ofToDataPathFS(dirPath); } - return fs::exists(dirPath) && fs::is_directory(dirPath); + return std::filesystem::exists(dirPath) && std::filesystem::is_directory(dirPath); } catch (std::exception & except) { ofLogError("ofDirectory") << "doesDirectoryExist(): couldn't find directory " << dirPath << ": " << except.what() << std::endl; @@ -1645,14 +1649,14 @@ bool ofDirectory::doesDirectoryExist(const fs::path& _dirPath, bool bRelativeToD } //------------------------------------------------------------------------------------------------------------ -bool ofDirectory::isDirectoryEmpty(const fs::path& _dirPath, bool bRelativeToData){ +bool ofDirectory::isDirectoryEmpty(const of::filesystem::path& _dirPath, bool bRelativeToData){ auto dirPath = _dirPath; if(bRelativeToData){ dirPath = ofToDataPathFS(dirPath); } - if(!dirPath.empty() && fs::exists(dirPath) && fs::is_directory(dirPath)){ - return fs::directory_iterator(dirPath) == fs::directory_iterator(); + if(!dirPath.empty() && std::filesystem::exists(dirPath) && std::filesystem::is_directory(dirPath)){ + return std::filesystem::directory_iterator(dirPath) == std::filesystem::directory_iterator(); } return false; } @@ -1717,9 +1721,9 @@ vector::const_reverse_iterator ofDirectory::rend() const{ //------------------------------------------------------------------------------------------------------------ // FIXME: - re-avail -string ofFilePath::addLeadingSlash(const fs::path & _path){ +string ofFilePath::addLeadingSlash(const of::filesystem::path & _path){ auto path = ofPathToString(_path); - auto sep = fs::path("/").make_preferred(); + auto sep = of::filesystem::path("/").make_preferred(); if(!path.empty()){ if(ofToString(path[0]) != sep.string()) { return ofPathToString(sep / path); @@ -1730,15 +1734,15 @@ string ofFilePath::addLeadingSlash(const fs::path & _path){ //------------------------------------------------------------------------------------------------------------ // FIXME: - re-avail - this function have to be completely rewritten, so I'll keep string conversions as it is -std::string ofFilePath::addTrailingSlash(const fs::path & _path){ +std::string ofFilePath::addTrailingSlash(const of::filesystem::path & _path){ #if defined(OF_USING_STD_FS) && !defined(OF_USE_EXPERIMENTAL_FS) if(_path.empty()) { return {}; } - return ofPathToString(fs::path(_path).make_preferred() / ""); + return ofPathToString(of::filesystem::path(_path).make_preferred() / ""); #else - auto path = fs::path(_path).make_preferred(); - auto sep = fs::path("/").make_preferred(); + auto path = of::filesystem::path(_path).make_preferred(); + auto sep = of::filesystem::path("/").make_preferred(); if(!path.empty()){ if(ofToString(path.string().back()) != sep.string()){ path = path / sep; @@ -1751,19 +1755,19 @@ std::string ofFilePath::addTrailingSlash(const fs::path & _path){ //------------------------------------------------------------------------------------------------------------ // FIXME: - start using fs::path.extension() -string ofFilePath::getFileExt(const fs::path & filename){ +std::string ofFilePath::getFileExt(const of::filesystem::path & filename){ return ofFile(filename,ofFile::Reference).getExtension(); } //------------------------------------------------------------------------------------------------------------ // FIXME: - Deprecate and suggest replace_extension instead -std::string ofFilePath::removeExt(const fs::path & _filename){ +std::string ofFilePath::removeExt(const of::filesystem::path & _filename){ auto filename = _filename; return ofPathToString(filename.replace_extension()); } //------------------------------------------------------------------------------------------------------------ -fs::path ofFilePath::getPathForDirectoryFS(const fs::path & path){ +of::filesystem::path ofFilePath::getPathForDirectoryFS(const of::filesystem::path & path){ // if a trailing slash is missing from a path, this will clean it up // if it's a windows-style "\" path it will add a "\" // if it's a unix-style "/" path it will add a "/" @@ -1772,7 +1776,7 @@ fs::path ofFilePath::getPathForDirectoryFS(const fs::path & path){ if(path.empty()) return {}; return path / ""; #else - auto sep = fs::path("/").make_preferred(); + auto sep = of::filesystem::path("/").make_preferred(); if(!path.empty() && ofToString(path.back()) != sep.string()){ return path / sep; }else{ @@ -1784,14 +1788,15 @@ fs::path ofFilePath::getPathForDirectoryFS(const fs::path & path){ //------------------------------------------------------------------------------------------------------------ // FIXME: Deprecate this seems over complicated and not useful anymore, using filesystem -string ofFilePath::getPathForDirectory(const fs::path & path){ - return ofPathToString(ofFilePath::getPathForDirectoryFS(path)); +of::filesystem::path ofFilePath::getPathForDirectory(const of::filesystem::path & path){ + return ofFilePath::getPathForDirectoryFS(path); } //------------------------------------------------------------------------------------------------------------ // FIXME: - re-avail -string ofFilePath::removeTrailingSlash(const fs::path & _path){ +// implementation differs between string and path — keep string->string version around? +std::string ofFilePath::removeTrailingSlash(const std::string & _path){ auto path = ofPathToString(_path); if(path.length() > 0 && (path[path.length() - 1] == '/' || path[path.length() - 1] == '\\')){ path = path.substr(0, path.length() - 1); @@ -1799,27 +1804,35 @@ string ofFilePath::removeTrailingSlash(const fs::path & _path){ return path; } +of::filesystem::path ofFilePath::removeTrailingSlash(of::filesystem::path & path){ + if (path.has_filename() == false) { + path.remove_filename(); + } + return path; +} + + //------------------------------------------------------------------------------------------------------------ -string ofFilePath::getFileName(const fs::path & filePath, bool bRelativeToData){ +string ofFilePath::getFileName(const of::filesystem::path & filePath, bool bRelativeToData){ return ofPathToString(filePath.filename()); } //------------------------------------------------------------------------------------------------------------ -string ofFilePath::getFileName(const fs::path & filePath){ +string ofFilePath::getFileName(const of::filesystem::path & filePath){ return ofPathToString(filePath.filename()); } //------------------------------------------------------------------------------------------------------------ // FIXME: - suggest using stem() instead -string ofFilePath::getBaseName(const fs::path & filePath){ +string ofFilePath::getBaseName(const of::filesystem::path & filePath){ return ofPathToString(filePath.stem()); } //------------------------------------------------------------------------------------------------------------ // MARK: - near future FS //fs::path ofFilePath::getEnclosingDirectoryFS(const fs::path & _filePath, bool bRelativeToData){ -std::string ofFilePath::getEnclosingDirectory(const fs::path & _filePath, bool bRelativeToData){ +of::filesystem::path ofFilePath::getEnclosingDirectory(const of::filesystem::path & _filePath, bool bRelativeToData){ auto fp = _filePath; if(bRelativeToData){ fp = ofToDataPath(fp); @@ -1828,48 +1841,48 @@ std::string ofFilePath::getEnclosingDirectory(const fs::path & _filePath, bool b } //------------------------------------------------------------------------------------------------------------ -bool ofFilePath::createEnclosingDirectory(const fs::path& filePath, bool bRelativeToData, bool bRecursive) { +bool ofFilePath::createEnclosingDirectory(const of::filesystem::path& filePath, bool bRelativeToData, bool bRecursive) { return ofDirectory::createDirectory(ofFilePath::getEnclosingDirectory(filePath,bRelativeToData), bRelativeToData, bRecursive); } //------------------------------------------------------------------------------------------------------------ // MARK: - near future FS -fs::path ofFilePath::getAbsolutePathFS(const fs::path & path, bool bRelativeToData){ +of::filesystem::path ofFilePath::getAbsolutePathFS(const of::filesystem::path & path, bool bRelativeToData){ if(bRelativeToData){ return ofToDataPath(path, true); }else{ try{ - return fs::canonical(fs::absolute(path)); + return std::filesystem::canonical(std::filesystem::absolute(path)); }catch(...){ - return fs::absolute(path); + return std::filesystem::absolute(path); } } } //------------------------------------------------------------------------------------------------------------ -std::string ofFilePath::getAbsolutePath(const fs::path& path, bool bRelativeToData){ +of::filesystem::path ofFilePath::getAbsolutePath(const of::filesystem::path& path, bool bRelativeToData){ return ofPathToString(ofFilePath::getAbsolutePathFS(path, bRelativeToData)); } //------------------------------------------------------------------------------------------------------------ -bool ofFilePath::isAbsolute(const fs::path& path){ - return fs::path(path).is_absolute(); +bool ofFilePath::isAbsolute(const of::filesystem::path& path){ + return path.is_absolute(); } //------------------------------------------------------------------------------------------------------------ string ofFilePath::getCurrentWorkingDirectory(){ - return ofPathToString(fs::current_path()); + return ofPathToString(std::filesystem::current_path()); } //------------------------------------------------------------------------------------------------------------ // FIXME: deprecate. helper function more complex than actual solution -std::string ofFilePath::join(const fs::path& path1, const fs::path& path2){ +of::filesystem::path ofFilePath::join(const of::filesystem::path& path1, const of::filesystem::path& path2){ // FIXME: deprecate when possible. helper function more complex than actual solution - return ofPathToString(path1 / path2); + return path1 / path2; } //------------------------------------------------------------------------------------------------------------ -fs::path ofFilePath::getCurrentExePathFS(){ +of::filesystem::path ofFilePath::getCurrentExePathFS(){ #if defined(TARGET_LINUX) || defined(TARGET_ANDROID) char buff[FILENAME_MAX]; ssize_t size = readlink("/proc/self/exe", buff, sizeof(buff) - 1); @@ -1900,22 +1913,22 @@ fs::path ofFilePath::getCurrentExePathFS(){ } //------------------------------------------------------------------------------------------------------------ -std::string ofFilePath::getCurrentExePath(){ - return ofPathToString(getCurrentExePathFS()); +of::filesystem::path ofFilePath::getCurrentExePath(){ + return getCurrentExePathFS(); } //------------------------------------------------------------------------------------------------------------ -fs::path ofFilePath::getCurrentExeDirFS(){ +of::filesystem::path ofFilePath::getCurrentExeDirFS(){ return ofFilePath::getCurrentExePathFS().parent_path() / ""; } //------------------------------------------------------------------------------------------------------------ -std::string ofFilePath::getCurrentExeDir(){ - return ofPathToString(getCurrentExeDirFS()); +of::filesystem::path ofFilePath::getCurrentExeDir(){ + return getCurrentExeDirFS(); } //------------------------------------------------------------------------------------------------------------ -string ofFilePath::getUserHomeDir(){ +of::filesystem::path ofFilePath::getUserHomeDir(){ #ifdef TARGET_WIN32 // getenv will return any Environent Variable on Windows // USERPROFILE is the key on Windows 7 but it might be HOME @@ -1931,8 +1944,8 @@ string ofFilePath::getUserHomeDir(){ // FIXME: - Deprecate near future. Advise to use fs::relative(to, from) instead //-------------------------------------------------- -std::string ofFilePath::makeRelative(const fs::path & from, const fs::path & to) { - return ofPathToString(fs::relative(to, from)); +of::filesystem::path ofFilePath::makeRelative(const of::filesystem::path & from, const of::filesystem::path & to) { + return std::filesystem::relative(to, from); } //-------------------------------------------------- @@ -1948,7 +1961,7 @@ void ofDisableDataPath(){ //-------------------------------------------------- bool ofRestoreWorkingDirectoryToDefault(){ try{ - fs::current_path(defaultWorkingDirectory()); + std::filesystem::current_path(defaultWorkingDirectory()); return true; }catch(...){ return false; @@ -1956,12 +1969,13 @@ bool ofRestoreWorkingDirectoryToDefault(){ } //-------------------------------------------------- -void ofSetDataPathRoot(const fs::path& newRoot){ +void ofSetDataPathRoot(const of::filesystem::path& newRoot){ dataPathRoot() = newRoot; } //-------------------------------------------------- -fs::path ofToDataPathFS(const fs::path & path, bool makeAbsolute){ +of::filesystem::path ofToDataPathFS(const of::filesystem::path & in_path, bool makeAbsolute){ + of::filesystem::path path {in_path} ; // don't propagate constness if (makeAbsolute && path.is_absolute()) { return path; } @@ -1974,7 +1988,8 @@ fs::path ofToDataPathFS(const fs::path & path, bool makeAbsolute){ // if our Current Working Directory has changed (e.g. file open dialog) #ifdef TARGET_WIN32 - if (defaultWorkingDirectory() != fs::current_path()) { + // .native workaround for operator != confusion in of::filesystem::path + if (defaultWorkingDirectory().native() != std::filesystem::current_path().native()) { // change our cwd back to where it was on app load bool ret = ofRestoreWorkingDirectoryToDefault(); if(!ret){ @@ -1985,14 +2000,14 @@ fs::path ofToDataPathFS(const fs::path & path, bool makeAbsolute){ // this could be performed here, or wherever we might think we accidentally change the cwd, e.g. after file dialogs on windows const auto & dataPath = dataPathRoot(); - fs::path inputPath(path); - fs::path outputPath; + of::filesystem::path inputPath(path); + of::filesystem::path outputPath; // if path is already absolute, just return it if (inputPath.is_absolute()) { try { - auto outpath = fs::canonical(inputPath).make_preferred(); - if(fs::is_directory(outpath) && hasTrailingSlash){ + auto outpath = std::filesystem::canonical(inputPath).make_preferred(); + if(std::filesystem::is_directory(outpath) && hasTrailingSlash){ return ofFilePath::addTrailingSlash(outpath); }else{ return outpath; @@ -2012,14 +2027,14 @@ fs::path ofToDataPathFS(const fs::path & path, bool makeAbsolute){ // FIXME: unneeded after we remove string operations dirDataPath = ofFilePath::addTrailingSlash(dataPath); - auto relativeDirDataPath = ofFilePath::makeRelative(fs::current_path(), dataPath); + auto relativeDirDataPath = ofFilePath::makeRelative(std::filesystem::current_path(), dataPath); // FIXME: unneeded after we remove string operations relativeDirDataPath = ofFilePath::addTrailingSlash(relativeDirDataPath); // FIXME: this can be simplified without using string conversion // if (inputPath.string().find(dirDataPath.string()) != 0 && inputPath.string().find(relativeDirDataPath.string())!=0) { - if (inputPath.string().find(dirDataPath.string()) != 0 && inputPath.string().find(relativeDirDataPath)!=0) { + if (inputPath.string().find(dirDataPath.string()) != 0 && inputPath.string().find(relativeDirDataPath.string())!=0) { // inputPath doesn't contain data path already, so we build the output path as the inputPath relative to the dataPath if(makeAbsolute){ outputPath = dirDataPath / inputPath; @@ -2035,15 +2050,15 @@ fs::path ofToDataPathFS(const fs::path & path, bool makeAbsolute){ if(makeAbsolute){ // then we return the absolute form of the path try { - auto outpath = fs::canonical(fs::absolute(outputPath)).make_preferred(); - if(fs::is_directory(outpath) && hasTrailingSlash){ + auto outpath = std::filesystem::canonical(std::filesystem::absolute(outputPath)).make_preferred(); + if(std::filesystem::is_directory(outpath) && hasTrailingSlash){ return ofFilePath::addTrailingSlash(outpath); }else{ return outpath; } } catch (std::exception &) { - return fs::absolute(outputPath); + return std::filesystem::absolute(outputPath); } }else{ // or output the relative path @@ -2052,24 +2067,26 @@ fs::path ofToDataPathFS(const fs::path & path, bool makeAbsolute){ } //-------------------------------------------------- -std::string ofToDataPath(const fs::path & path, bool makeAbsolute){ - return ofPathToString(ofToDataPathFS(path, makeAbsolute)); +of::filesystem::path ofToDataPath(const of::filesystem::path & path, bool makeAbsolute){ + return ofToDataPathFS(path, makeAbsolute); } //-------------------------------------------------- // Function used internally in OF core. API can change later -std::string ofPathToString(const fs::path & path) { +std::string ofPathToString(const of::filesystem::path & path) { try { return path.string(); - } catch(fs::filesystem_error & e) { - ofLogError("ofFileUtils") << "ofPathToString: error converting fs::path to string " << e.what(); + } catch(std::filesystem::filesystem_error & e) { + ofLogError("ofFileUtils") << "ofPathToString: filesystem error converting fs::path to string " << e.what(); + } catch (std::system_error& e) { + ofLogError("ofFileUtils") << "ofPathToString: system error converting fs::path to string " << e.what(); } return {}; } //-------------------------------------------------- // Function used internally in OF core. API can change later -std::string ofGetExtensionLower(const fs::path & path) { +std::string ofGetExtensionLower(const of::filesystem::path & path) { auto ext = path.extension().generic_string(); std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c){ return std::tolower(c); }); diff --git a/libs/openFrameworks/utils/ofFileUtils.h b/libs/openFrameworks/utils/ofFileUtils.h index c2ed03af9f3..5a008f8292f 100644 --- a/libs/openFrameworks/utils/ofFileUtils.h +++ b/libs/openFrameworks/utils/ofFileUtils.h @@ -326,7 +326,8 @@ class ofFilePath { /// /// \param path directory path /// \returns path minus trailing slash - static std::string removeTrailingSlash(const of::filesystem::path & path); + static std::string removeTrailingSlash(const std::string & _path); + static of::filesystem::path removeTrailingSlash(of::filesystem::path & path); /// Cleaned up a directory path by adding a trailing slash if needed. /// @@ -335,7 +336,7 @@ class ofFilePath { /// /// \param path directory path /// \returns cleaned path + trailing slash (if needed) - static std::string getPathForDirectory(const of::filesystem::path & path); + static of::filesystem::path getPathForDirectory(const of::filesystem::path & path); static of::filesystem::path getPathForDirectoryFS(const of::filesystem::path & path); /// Get the absolute, full path for a given path, @@ -347,7 +348,7 @@ class ofFilePath { /// "../../" /// \returns absolute path // FIXME: - Deprecate - static std::string getAbsolutePath(const of::filesystem::path & path, bool bRelativeToData = true); + static of::filesystem::path getAbsolutePath(const of::filesystem::path & path, bool bRelativeToData = true); static of::filesystem::path getAbsolutePathFS(const of::filesystem::path & path, bool bRelativeToData = true); /// Check if a path is an absolute (aka a full path), @@ -393,7 +394,7 @@ class ofFilePath { /// are *not* in the data folder and want the direct path without relative /// "../../" ///\returns enclosing directory - static std::string getEnclosingDirectory(const of::filesystem::path & filePath, bool bRelativeToData = true); + static of::filesystem::path getEnclosingDirectory(const of::filesystem::path & filePath, bool bRelativeToData = true); /// Create the enclosing parent directory of a path, ie. /// "images" is the enclosing directory of "duck.jpg" = "images/duck.jpg". @@ -425,7 +426,7 @@ class ofFilePath { /// \param path1 left half of the path to join /// \param path2 right half of the path to join /// \returns joined path - static std::string join(const of::filesystem::path & path1, const of::filesystem::path & path2); + static of::filesystem::path join(const of::filesystem::path & path1, const of::filesystem::path & path2); /// Get the full path to the application's executable file. /// @@ -435,7 +436,7 @@ class ofFilePath { /// /// \returns current executable path static of::filesystem::path getCurrentExePathFS(); - static std::string getCurrentExePath(); + static of::filesystem::path getCurrentExePath(); /// Get the full path to the application's parent directory. /// @@ -444,7 +445,7 @@ class ofFilePath { /// /// \returns current executable directory static of::filesystem::path getCurrentExeDirFS(); - static std::string getCurrentExeDir(); + static of::filesystem::path getCurrentExeDir(); /// Get the absolute path to the user's home directory. /// @@ -453,7 +454,7 @@ class ofFilePath { /// Linux: /home/ /// /// \returns home directory path - static std::string getUserHomeDir(); + static of::filesystem::path getUserHomeDir(); /// Make one path relative to another, /// ie. the relative path of "images/felines/lions" to @@ -462,7 +463,7 @@ class ofFilePath { /// \param from starting path /// \param to destination path /// \returns relative path - static std::string makeRelative(const of::filesystem::path & from, const of::filesystem::path & to); + static of::filesystem::path makeRelative(const of::filesystem::path & from, const of::filesystem::path & to); }; /// \class ofFile @@ -511,6 +512,8 @@ class ofFile : public std::fstream { /// /// \param mom ofFile instance source ofFile & operator=(const ofFile & mom); + +// operator of::filesystem::path() { return getAbsolutePath(); } ~ofFile(); @@ -574,7 +577,7 @@ class ofFile : public std::fstream { /// Get the current path. /// /// \returns current path - std::string path() const; + of::filesystem::path path() const; of::filesystem::path pathFS() const; /// Get the current path without its extension, @@ -609,7 +612,7 @@ class ofFile : public std::fstream { /// /// \returns current path as an absolute path // MARK: - near future FS - std::string getAbsolutePath() const; + of::filesystem::path getAbsolutePath() const; /// Check if the current path is readable. /// @@ -764,10 +767,15 @@ class ofFile : public std::fstream { /// \return output stream std::filebuf * getFileBuffer() const; + operator std::filesystem::path() { + return myFile; + } + +#if defined(OF_ENABLE_TOLERANT_NARROW_PATH_CONVERSION) operator of::filesystem::path() { return myFile; } - // +#endif operator of::filesystem::path() const { return myFile; } @@ -880,14 +888,14 @@ class ofDirectory { /// /// \returns current path // MARK: - near future FS - std::string path() const; + of::filesystem::path path() const; /// Get the absolute, full path of the directory, /// ie. "images" -> "/Users/mickey/of/apps/myApps/Donald/bin/data/images". /// /// \return current path as an absolute path // MARK: - near future FS - std::string getAbsolutePath() const; + of::filesystem::path getAbsolutePath() const; of::filesystem::path getAbsolutePathFS() const; /// Check if the current path is readable. @@ -1142,9 +1150,15 @@ class ofDirectory { bool operator>(const ofDirectory & dir) const; bool operator>=(const ofDirectory & dir) const; + operator std::filesystem::path() { + return myDir; + } + +#if defined(OF_ENABLE_TOLERANT_NARROW_PATH_CONVERSION) operator of::filesystem::path() { return myDir; } +#endif operator of::filesystem::path() const { return myDir; @@ -1233,9 +1247,10 @@ void ofDisableDataPath(); /// \param absolute Set to true to return an absolute path. /// \returns the new path, unless paths were disabled with ofDisableDataPath(). -of::filesystem::path ofToDataPathFS(const of::filesystem::path & path, bool absolute=false); +of::filesystem::path ofToDataPathFS(const of::filesystem::path & path, bool absolute = false); + +of::filesystem::path ofToDataPath(const of::filesystem::path & path, bool absolute = false); -std::string ofToDataPath(const of::filesystem::path & path, bool absolute = false); /// \brief Reset the working directory to the platform default. /// diff --git a/libs/openFrameworks/utils/ofFilesystemPath.h b/libs/openFrameworks/utils/ofFilesystemPath.h new file mode 100644 index 00000000000..7975901ece8 --- /dev/null +++ b/libs/openFrameworks/utils/ofFilesystemPath.h @@ -0,0 +1,233 @@ +#ifndef OF_FILESYSTEM_PATH_H +#define OF_FILESYSTEM_PATH_H + +#include +#include +#include +#include + +namespace of::filesystem { + +class path { + + // as per https://github.com/cplusplus/draft/releases/tag/n4917 + + // general approach to return type: + // - use `path` and path &` to wrap std:: return values + // - use bool when bool (for self-documenting API) + // - use (const) auto (inheriting from std:: implementation) for others + +private: + std::filesystem::path path_; // simple composition + +public: + // MARK: construction + path() = default; + path(const std::filesystem::path& p) : path_(p) {} + path(std::filesystem::path&& p) noexcept : path_(std::move(p)) {} + path(const std::string& s) : path_(s) {} + path(const char* s) : path_(s) {} + path(const wchar_t* s) : path_(s) {} + path(const path& other) = default; + path& operator=(const path& other) = default; + path(path&& other) noexcept = default; + path& operator=(path&& other) noexcept = default; + + void clear() noexcept { + path_.clear(); + } + + operator std::filesystem::path() const { return path_; } + explicit operator const std::filesystem::path::value_type*() const { return path_.c_str(); } + + // MARK: string conversions + + auto wstring() const { return path_.wstring(); } + auto generic_string() const { return path_.generic_string(); } + auto generic_wstring() const { return path_.generic_wstring(); } + auto generic_u8string() const { return path_.generic_u8string(); } + auto generic_u16string() const { return path_.generic_u16string(); } + auto generic_u32string() const { return path_.generic_u32string(); } + auto string() const { return path_.string(); } + auto native() const noexcept { return path_.native(); } + auto u8string() const { return path_.u8string(); } + auto u16string() const { return path_.u16string(); } + auto u32string() const { return path_.u32string(); } + const auto c_str() const noexcept { return path_.c_str(); } + + const std::filesystem::path& native_path() const { return path_; } + + static constexpr auto preferred_separator = std::filesystem::path::preferred_separator; + + bool empty() const noexcept { return path_.empty(); } + bool is_absolute() const { return path_.is_absolute(); } + bool is_relative() const { return path_.is_relative(); } + +#if defined(TARGET_WIN32) // superfluous but usefull to facilitate testing on mac/linux + + // TODO better (ideal) impl this just copy-pasted for proof of concept + mutable std::string cached_narrow_str_; + const char* to_narrow_cstr() const { + size_t size_needed = std::wcstombs(nullptr, wstring().c_str(), 0) + 1; + if (size_needed == static_cast(-1)) { + throw std::runtime_error("Conversion error from wstring to string"); + } + cached_narrow_str_.resize(size_needed); + std::wcstombs(&cached_narrow_str_[0], wstring().c_str(), size_needed); + return cached_narrow_str_.c_str(); + } + + operator std::wstring() const { return path_.wstring(); } + operator const char*() const { return to_narrow_cstr(); } // should try catch on win + operator std::string() const { return path_.string(); } // should try catch on win + explicit operator const std::string() const { return path_.string(); } // should try catch on win +#else + operator std::filesystem::path::string_type() const { return path_.string(); } + explicit operator const std::filesystem::path::string_type() const { return path_.string(); } +#endif + + + + // MARK: std::filesystem forwards + bool exists() const { return std::filesystem::exists(path_); } + bool is_directory() const { return std::filesystem::is_directory(path_); } + bool is_regular_file() const { return std::filesystem::is_regular_file(path_); } + bool is_symlink() const { return std::filesystem::is_symlink(path_); } + bool is_block_file() const { return std::filesystem::is_block_file(path_); } + bool is_character_file() const { return std::filesystem::is_character_file(path_); } + bool is_empty() const { return std::filesystem::is_empty(path_); } + auto file_size() const { return std::filesystem::file_size(path_); } + auto last_write_time() const { return std::filesystem::last_write_time(path_); } + auto get_permissions() const { return std::filesystem::status(path_).permissions(); } + + // MARK: path type + path lexically_normal() const { + return path(path_.lexically_normal()); + } + + template + path lexically_relative(Args&&... args) const { + return path(path_.lexically_relative(std::forward(args)...)); + } + + template + path lexically_proximate(Args&&... args) const { + return path(path_.lexically_proximate(std::forward(args)...)); + } + + // MARK: comparison + // TODO: C++20: spaceship simplification + template bool operator==(T&& other) const noexcept { return path_ == std::forward(other); } + template bool operator!=(T&& other) const noexcept { return path_ != std::forward(other); } + template bool operator<(T&& other) const noexcept { return path_ < std::forward(other); } + template bool operator<=(T&& other) const noexcept { return path_ <= std::forward(other); } + template bool operator>(T&& other) const noexcept { return path_ > std::forward(other); } + template bool operator>=(T&& other) const noexcept { return path_ >= std::forward(other); } + + bool operator!() const noexcept { return empty(); } + + template + auto compare(Args&&... args) const { return path_.compare(std::forward(args)...); } + + void swap(path & other) noexcept { path_.swap(other.path_); } + + + // MARK: path transformation (return *this) + path& replace_extension(const path & ext = std::filesystem::path()) { + path_.replace_extension(ext); + return *this; + } + + path& replace_filename(const path & ext = std::filesystem::path()) { + path_.replace_filename(ext); + return *this; + } + + template + path& assign(T&& p) noexcept { + path_.assign(std::move(std::forward(p))); + return *this; + } + + path& append(path&& p) noexcept { + path_ /= std::move(p.path_); + return *this; + } + + path& operator/=(path&& p) noexcept { + path_ /= std::move(p.path_); + return *this; + } + + template + path& operator+=(const T& rhs) { + path_ += rhs; + return *this; + } + + template + path& concat(const T& rhs) { + path_ += rhs; + return *this; + } + + path& make_preferred() { + path_.make_preferred(); + return *this; + } + + path& remove_filename() { + path_.remove_filename(); + return *this; + } + + // MARK: other operators + template + const friend path operator/(const LHS& lhs, const path& rhs) { + return path(lhs / rhs.path_); + } + + template + const friend path operator/(const path& lhs, const RHS& rhs) { + return path(lhs.path_ / rhs); + } + + const friend path operator/(const path& lhs, const path& rhs) { + return path(lhs.path_ / rhs.path_); + } + + template + const friend path operator+(const LHS& lhs, const path& rhs) { + return path(lhs + rhs.path_.string()); + } + + template + const friend path operator+(const path& lhs, const RHS& rhs) { + return path(lhs.path_.string() + rhs); + } + + // MARK: other sub paths + path root_name() const { return path(path_.root_name()); } + path root_directory() const { return path(path_.root_directory()); } + path root_path() const { return path(path_.root_path()); } + path relative_path() const { return path(path_.relative_path()); } + path parent_path() const { return path(path_.parent_path()); } + path filename() const { return path(path_.filename()); } + path stem() const { return path(path_.stem()); } + path extension() const { return path(path_.extension()); } + + // MARK: file info + bool has_extension() const { return path_.has_extension(); } + bool has_filename() const { return path_.has_filename(); } + bool has_root_path() const { return path_.has_root_path(); } + bool has_root_name() const { return path_.has_root_name(); } + bool has_root_directory() const { return path_.has_root_directory(); } + bool has_relative_path() const { return path_.has_relative_path(); } + bool has_stem() const { return path_.has_stem(); } + + friend std::ostream& operator<<(std::ostream& os, const path& p) { + return os << p.string(); + } +}; +} +#endif // OF_FILESYSTEM_PATH_H diff --git a/scripts/msys2/buildAllExamples.sh b/scripts/msys2/buildAllExamples.sh index 389f58eb68a..277171503f5 100755 --- a/scripts/msys2/buildAllExamples.sh +++ b/scripts/msys2/buildAllExamples.sh @@ -2,7 +2,13 @@ export LC_ALL=C -examples_dir=../../examples +#!/bin/bash +if [ -z "$1" ]; then + examples_dir=../../examples +else + examples_dir="$1" +fi + examples_prefix="$examples_dir/" system=msys2 diff --git a/tests/utils/fileUtils/src/main.cpp b/tests/utils/fileUtils/src/main.cpp index 59dbdb25a27..afb4abd80ea 100644 --- a/tests/utils/fileUtils/src/main.cpp +++ b/tests/utils/fileUtils/src/main.cpp @@ -183,12 +183,11 @@ class ofApp: public ofxUnitTestsApp{ ofxTestEq(ofFilePath::join("d1","d2"),"d1/d2","ofFilePath::join",ofFilePath::join("d1","d2")); #endif - ofxTest(of::filesystem::exists(ofFile("test.txt")), "ofFile cast to filesystem::path"); - ofxTest(of::filesystem::exists(ofDirectory("d1")), "ofDirectory cast to filesystem::path"); - - - - + ofxTest(std::filesystem::exists(ofFile("test.txt")), "ofFile cast to filesystem::path"); + ofxTest(std::filesystem::exists(ofDirectory("d1")), "ofDirectory cast to filesystem::path"); + + std::string narrow = ofToDataPath(""); + ofxTest(std::filesystem::exists(narrow), "narrow paths on windows"); //======================================================================== ofLogNotice() << ""; @@ -268,12 +267,12 @@ class ofApp: public ofxUnitTestsApp{ ofDirectory currentVideoDirectory(ofToDataPath("..\\..\\..\\video", true)); auto path = currentVideoDirectory.path(); std::string pathEnd("data\\..\\..\\..\\video\\"); - ofxTestEq(path.substr(path.size()-pathEnd.size()), pathEnd, "#4564"); + ofxTestEq(path.native().substr(path.native().size()-pathEnd.size()), pathEnd, "#4564"); }else{ ofDirectory currentVideoDirectory(ofToDataPath("../../../video", true)); auto path = currentVideoDirectory.path(); std::string pathEnd("data/../../../video/"); - ofxTestEq(path.substr(path.size()-pathEnd.size()), pathEnd, "#4564"); + ofxTestEq(path.native().substr(path.native().size()-pathEnd.size()), pathEnd, "#4564"); } } }; @@ -283,10 +282,10 @@ class ofApp: public ofxUnitTestsApp{ #include "ofAppRunner.h" //======================================================================== int main( ){ - initial_cwd = of::filesystem::current_path(); + initial_cwd = std::filesystem::current_path(); ofInit(); auto window = std::make_shared(); auto app = std::make_shared(); ofRunApp(window, app); return ofRunMainLoop(); -} \ No newline at end of file +}