// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. #pragma once #include #if defined _WIN32 || defined WINCE # include const char dir_separators[] = "/\\"; namespace { struct dirent { const char* d_name; }; struct DIR { #if defined(WINRT) || defined(_WIN32_WCE) WIN32_FIND_DATAW data; #else WIN32_FIND_DATAA data; #endif HANDLE handle; dirent ent; #ifdef WINRT DIR() { } ~DIR() { if( ent.d_name ) delete[] ent.d_name; } #endif }; DIR* opendir( const char* path ) { DIR* dir = new DIR; dir->ent.d_name = 0; #if defined(WINRT) || defined(_WIN32_WCE) cv::String full_path = cv::String( path ) + "\\*"; wchar_t wfull_path[MAX_PATH]; size_t copied = mbstowcs( wfull_path, full_path.c_str(), MAX_PATH ); CV_Assert( (copied != MAX_PATH) && (copied != (size_t)-1) ); dir->handle = ::FindFirstFileExW( wfull_path, FindExInfoStandard, &dir->data, FindExSearchNameMatch, NULL, 0 ); #else dir->handle = ::FindFirstFileExA( (std::string( path ) + "\\*").c_str(), FindExInfoStandard, &dir->data, FindExSearchNameMatch, NULL, 0 ); #endif if( dir->handle == INVALID_HANDLE_VALUE ) { /*closedir will do all cleanup*/ delete dir; return 0; } return dir; } dirent* readdir( DIR* dir ) { #if defined(WINRT) || defined(_WIN32_WCE) if( dir->ent.d_name != 0 ) { if( ::FindNextFileW( dir->handle, &dir->data ) != TRUE ) return 0; } size_t asize = wcstombs( NULL, dir->data.cFileName, 0 ); CV_Assert( (asize != 0) && (asize != (size_t)-1) ); char* aname = new char[asize + 1]; aname[asize] = 0; wcstombs( aname, dir->data.cFileName, asize ); dir->ent.d_name = aname; #else if( dir->ent.d_name != 0 ) { if( ::FindNextFileA( dir->handle, &dir->data ) != TRUE ) return 0; } dir->ent.d_name = dir->data.cFileName; #endif return &dir->ent; } void closedir( DIR* dir ) { ::FindClose( dir->handle ); delete dir; } } #else # include # include const char dir_separators[] = "/"; #endif #ifdef _WIN32 static const char native_separator = '\\'; #else static const char native_separator = '/'; #endif static inline bool isPathSeparator( char c ) { return c == '/' || c == '\\'; } std::string join( const std::string& base, const std::string& path ) { if( base.empty() ) return path; if( path.empty() ) return base; bool baseSep = isPathSeparator( base[base.size() - 1] ); bool pathSep = isPathSeparator( path[0] ); std::string result; if( baseSep && pathSep ) { result = base + path.substr( 1 ); } else if( !baseSep && !pathSep ) { result = base + native_separator + path; } else { result = base + path; } return result; } static bool wildcmp( const char *string, const char *wild ) { // Based on wildcmp written by Jack Handy - jakkhandy@hotmail.com const char *cp = 0, *mp = 0; while( (*string) && (*wild != '*') ) { if( (*wild != *string) && (*wild != '?') ) { return false; } wild++; string++; } while( *string ) { if( *wild == '*' ) { if( !*++wild ) { return true; } mp = wild; cp = string + 1; } else if( (*wild == *string) || (*wild == '?') ) { wild++; string++; } else { wild = mp; string = cp++; } } while( *wild == '*' ) { wild++; } return *wild == 0; } static bool isDir( const std::string& path, DIR* dir ) { #if defined _WIN32 || defined WINCE DWORD attributes; BOOL status = TRUE; if( dir ) attributes = dir->data.dwFileAttributes; else { WIN32_FILE_ATTRIBUTE_DATA all_attrs; #ifdef WINRT wchar_t wpath[MAX_PATH]; size_t copied = mbstowcs( wpath, path.c_str(), MAX_PATH ); CV_Assert( (copied != MAX_PATH) && (copied != (size_t)-1) ); status = ::GetFileAttributesExW( wpath, GetFileExInfoStandard, &all_attrs ); #else status = ::GetFileAttributesExA( path.c_str(), GetFileExInfoStandard, &all_attrs ); #endif attributes = all_attrs.dwFileAttributes; } return status && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); #else (void)dir; // avoid warnings about unused params struct stat stat_buf; if( 0 != stat( path.c_str(), &stat_buf ) ) return false; int is_dir = S_ISDIR( stat_buf.st_mode ); return is_dir != 0; #endif } static void glob_rec( const std::string & directory, const std::string & wildchart, std::vector& result, bool recursive, bool includeDirectories, const std::string & pathPrefix ) { DIR *dir; if( (dir = opendir( directory.c_str() )) != 0 ) { /* find all the files and directories within directory */ try { struct dirent *ent; while( (ent = readdir( dir )) != 0 ) { const char* name = ent->d_name; if( (name[0] == 0) || (name[0] == '.' && name[1] == 0) || (name[0] == '.' && name[1] == '.' && name[2] == 0) ) continue; std::string path = join( directory, name ); std::string entry = join( pathPrefix, name ); if( isDir( path, dir ) ) { if( recursive ) glob_rec( path, wildchart, result, recursive, includeDirectories, entry ); if( !includeDirectories ) continue; } if( wildchart.empty() || wildcmp( name, wildchart.c_str() ) ) result.push_back( entry ); } } catch( ... ) { closedir( dir ); throw; } closedir( dir ); } else { throw std::runtime_error( "could not open directory: " + directory ); } } static void glob( const std::string & directory, const std::string & spec, std::function< void( std::string const & ) > fn, bool recursive = true, bool includeDirectories = false ) { std::vector< std::string > results; glob_rec( directory, spec, results, recursive, includeDirectories, "" ); for( auto r : results ) fn( r ); } static std::string get_parent( std::string const & path, std::string * basename = nullptr ) { // Returns the parent and leaf for the given path: // /foo/bar/ -> '/foo/bar' and '' (empty) // blah/.. -> 'blah' and '..' auto x = path.find_last_of( dir_separators ); if( x == std::string::npos ) return std::string(); if( basename ) *basename = path.substr( x + 1 ); return std::string( path, 0, x ); }