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
296 lines
7.3 KiB
2 months ago
|
// 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 );
|
||
|
}
|