You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
7.3 KiB

// 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 <string>
#if defined _WIN32 || defined WINCE
# include <windows.h>
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 <dirent.h>
# include <sys/stat.h>
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 - <A href="mailto:jakkhandy@hotmail.com">jakkhandy@hotmail.com</A>
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<std::string>& 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 );
}