ENH: Push glob to the kwsys

This commit is contained in:
Andy Cedilnik 2005-10-18 14:08:55 -04:00
parent 37dc4bdc6e
commit fdc4795b91
4 changed files with 518 additions and 1 deletions

View File

@ -86,6 +86,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# Enable all components.
SET(KWSYS_USE_Base64 1)
SET(KWSYS_USE_Directory 1)
SET(KWSYS_USE_Glob 1)
SET(KWSYS_USE_Process 1)
SET(KWSYS_USE_RegularExpression 1)
SET(KWSYS_USE_Registry 1)
@ -416,9 +417,14 @@ SET(KWSYS_HXX_FILES Configure hashtable hash_fun hash_map hash_set)
IF(KWSYS_USE_SystemTools)
SET(KWSYS_USE_Directory 1)
ENDIF(KWSYS_USE_SystemTools)
IF(KWSYS_USE_Glob)
SET(KWSYS_USE_Directory 1)
SET(KWSYS_USE_SystemTools 1)
SET(KWSYS_USE_RegularExpression 1)
ENDIF(KWSYS_USE_Glob)
# Add selected C++ classes.
SET(cppclasses Directory RegularExpression SystemTools CommandLineArguments Registry)
SET(cppclasses Directory Glob RegularExpression SystemTools CommandLineArguments Registry)
FOREACH(c ${cppclasses})
IF(KWSYS_USE_${c})
SET(KWSYS_CLASSES ${KWSYS_CLASSES} ${c})

428
Source/kwsys/Glob.cxx Normal file
View File

@ -0,0 +1,428 @@
/*=========================================================================
Program: KWSys - Kitware System Library
Module: $RCSfile$
Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Glob.hxx)
#include KWSYS_HEADER(Configure.hxx)
#include KWSYS_HEADER(RegularExpression.hxx)
#include KWSYS_HEADER(SystemTools.hxx)
#include KWSYS_HEADER(Directory.hxx)
#include KWSYS_HEADER(stl/string)
#include KWSYS_HEADER(stl/vector)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
# include "Glob.hxx.in"
# include "Configure.hxx.in"
# include "RegularExpression.hxx.in"
# include "SystemTools.hxx.in"
# include "kwsys_stl.hxx.in"
# include "kwsys_stl_string.hxx.in"
#endif
#include <ctype.h>
#include <stdio.h>
namespace KWSYS_NAMESPACE
{
#if defined( _WIN32 ) || defined( APPLE ) || defined( __CYGWIN__ )
// On Windows and apple, no difference between lower and upper case
#define CM_GLOB_CASE_INDEPENDENT
#endif
#if defined( _WIN32 ) || defined( __CYGWIN__ )
// Handle network paths
#define CM_GLOB_SUPPORT_NETWORK_PATHS
#endif
//----------------------------------------------------------------------------
class GlobInternals
{
public:
std::vector<std::string> Files;
std::vector<cmsys::RegularExpression> Expressions;
std::vector<std::string> TextExpressions;
};
//----------------------------------------------------------------------------
Glob::Glob()
{
m_Internals = new GlobInternals;
m_Recurse = false;
}
//----------------------------------------------------------------------------
Glob::~Glob()
{
delete m_Internals;
}
//----------------------------------------------------------------------------
void Glob::Escape(int ch, char* buffer)
{
if (! (
'a' <= ch && ch <= 'z' ||
'A' <= ch && ch <= 'Z' ||
'0' <= ch && ch <= '9') )
{
sprintf(buffer, "\\%c", ch);
}
else
{
#if defined( CM_GLOB_CASE_INDEPENDENT )
// On Windows and apple, no difference between lower and upper case
sprintf(buffer, "%c", tolower(ch));
#else
sprintf(buffer, "%c", ch);
#endif
}
}
//----------------------------------------------------------------------------
std::vector<std::string>& Glob::GetFiles()
{
return m_Internals->Files;
}
//----------------------------------------------------------------------------
std::string Glob::ConvertExpression(const std::string& expr)
{
std::string::size_type i = 0;
std::string::size_type n = expr.size();
std::string res = "^";
std::string stuff = "";
while ( i < n )
{
int c = expr[i];
i = i+1;
if ( c == '*' )
{
res = res + ".*";
}
else if ( c == '?' )
{
res = res + ".";
}
else if ( c == '[' )
{
std::string::size_type j = i;
if ( j < n && ( expr[j] == '!' || expr[j] == '^' ) )
{
j = j+1;
}
if ( j < n && expr[j] == ']' )
{
j = j+1;
}
while ( j < n && expr[j] != ']' )
{
j = j+1;
}
if ( j >= n )
{
res = res + "\\[";
}
else
{
stuff = "";
std::string::size_type cc;
for ( cc = i; cc < j; cc ++ )
{
if ( expr[cc] == '\\' )
{
stuff += "\\\\";
}
else
{
stuff += expr[cc];
}
}
i = j+1;
if ( stuff[0] == '!' || stuff[0] == '^' )
{
stuff = '^' + stuff.substr(1);
}
else if ( stuff[0] == '^' )
{
stuff = '\\' + stuff;
}
res = res + "[" + stuff + "]";
}
}
else
{
char buffer[100];
buffer[0] = 0;
this->Escape(c, buffer);
res = res + buffer;
}
}
return res + "$";
}
//----------------------------------------------------------------------------
void Glob::RecurseDirectory(std::string::size_type start,
const std::string& dir, bool dir_only)
{
cmsys::Directory d;
if ( !d.Load(dir.c_str()) )
{
return;
}
unsigned long cc;
std::string fullname;
std::string realname;
std::string fname;
for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
{
fname = d.GetFile(cc);
if ( strcmp(fname.c_str(), ".") == 0 ||
strcmp(fname.c_str(), "..") == 0 )
{
continue;
}
if ( start == 0 )
{
realname = dir + fname;
}
else
{
realname = dir + "/" + fname;
}
#if defined( CM_GLOB_CASE_INDEPENDENT )
// On Windows and apple, no difference between lower and upper case
fname = cmsys::SystemTools::LowerCase(fname);
#endif
if ( start == 0 )
{
fullname = dir + fname;
}
else
{
fullname = dir + "/" + fname;
}
if ( !dir_only || !cmsys::SystemTools::FileIsDirectory(realname.c_str()) )
{
if ( m_Internals->Expressions[m_Internals->Expressions.size()-1].find(fname.c_str()) )
{
m_Internals->Files.push_back(realname);
}
}
if ( cmsys::SystemTools::FileIsDirectory(realname.c_str()) )
{
this->RecurseDirectory(start+1, realname, dir_only);
}
}
}
//----------------------------------------------------------------------------
void Glob::ProcessDirectory(std::string::size_type start,
const std::string& dir, bool dir_only)
{
//std::cout << "ProcessDirectory: " << dir << std::endl;
bool last = ( start == m_Internals->Expressions.size()-1 );
if ( last && m_Recurse )
{
this->RecurseDirectory(start, dir, dir_only);
return;
}
cmsys::Directory d;
if ( !d.Load(dir.c_str()) )
{
return;
}
unsigned long cc;
std::string fullname;
std::string realname;
std::string fname;
for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ )
{
fname = d.GetFile(cc);
if ( strcmp(fname.c_str(), ".") == 0 ||
strcmp(fname.c_str(), "..") == 0 )
{
continue;
}
if ( start == 0 )
{
realname = dir + fname;
}
else
{
realname = dir + "/" + fname;
}
#if defined( CM_GLOB_CASE_INDEPENDENT )
// On Windows and apple, no difference between lower and upper case
fname = cmsys::SystemTools::LowerCase(fname);
#endif
if ( start == 0 )
{
fullname = dir + fname;
}
else
{
fullname = dir + "/" + fname;
}
//std::cout << "Look at file: " << fname << std::endl;
//std::cout << "Match: " << m_Internals->TextExpressions[start].c_str() << std::endl;
//std::cout << "Full name: " << fullname << std::endl;
if ( (!dir_only || !last) && !cmsys::SystemTools::FileIsDirectory(realname.c_str()) )
{
continue;
}
if ( m_Internals->Expressions[start].find(fname.c_str()) )
{
if ( last )
{
m_Internals->Files.push_back(realname);
}
else
{
this->ProcessDirectory(start+1, realname + "/", dir_only);
}
}
}
}
//----------------------------------------------------------------------------
bool Glob::FindFiles(const std::string& inexpr)
{
std::string cexpr;
std::string::size_type cc;
std::string expr = inexpr;
m_Internals->Expressions.clear();
m_Internals->Files.clear();
if ( !cmsys::SystemTools::FileIsFullPath(expr.c_str()) )
{
expr = cmsys::SystemTools::GetCurrentWorkingDirectory();
expr += "/" + inexpr;
}
std::string fexpr = expr;
int skip = 0;
int last_slash = 0;
for ( cc = 0; cc < expr.size(); cc ++ )
{
if ( cc > 0 && expr[cc] == '/' && expr[cc-1] != '\\' )
{
last_slash = cc;
}
if ( cc > 0 &&
(expr[cc] == '[' || expr[cc] == '?' || expr[cc] == '*') &&
expr[cc-1] != '\\' )
{
break;
}
}
if ( last_slash > 0 )
{
//std::cout << "I can skip: " << fexpr.substr(0, last_slash) << std::endl;
skip = last_slash;
}
if ( skip == 0 )
{
#if defined( CM_GLOB_SUPPORT_NETWORK_PATHS )
// Handle network paths
if ( expr[0] == '/' && expr[1] == '/' )
{
int cnt = 0;
for ( cc = 2; cc < expr.size(); cc ++ )
{
if ( expr[cc] == '/' )
{
cnt ++;
if ( cnt == 2 )
{
break;
}
}
}
skip = cc + 1;
}
else
#endif
// Handle drive letters on Windows
if ( expr[1] == ':' && expr[0] != '/' )
{
skip = 2;
}
}
if ( skip > 0 )
{
expr = expr.substr(skip);
}
cexpr = "";
for ( cc = 0; cc < expr.size(); cc ++ )
{
int ch = expr[cc];
if ( ch == '/' )
{
if ( cexpr.size() > 0 )
{
this->AddExpression(cexpr.c_str());
}
cexpr = "";
}
else
{
cexpr.append(1, (char)ch);
}
}
if ( cexpr.size() > 0 )
{
this->AddExpression(cexpr.c_str());
}
// Handle network paths
if ( skip > 0 )
{
this->ProcessDirectory(0, fexpr.substr(0, skip) + "/",
true);
}
else
{
this->ProcessDirectory(0, "/", true);
}
return true;
}
void Glob::AddExpression(const char* expr)
{
m_Internals->Expressions.push_back(
cmsys::RegularExpression(
this->ConvertExpression(expr).c_str()));
m_Internals->TextExpressions.push_back(this->ConvertExpression(expr));
}
} // namespace KWSYS_NAMESPACE

81
Source/kwsys/Glob.hxx.in Normal file
View File

@ -0,0 +1,81 @@
/*=========================================================================
Program: KWSys - Kitware System Library
Module: $RCSfile$
Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef @KWSYS_NAMESPACE@_Glob_hxx
#define @KWSYS_NAMESPACE@_Glob_hxx
#include <@KWSYS_NAMESPACE@/stl/string>
#include <@KWSYS_NAMESPACE@/stl/vector>
#include <@KWSYS_NAMESPACE@/Configure.h>
namespace @KWSYS_NAMESPACE@
{
class GlobInternals;
/** \class Glob
* \brief Portable globbing searches.
*
* Globbing expressions are much simpler than regular
* expressions. This class will search for files using
* globbing expressions.
*
* Finds all files that match a given globbing expression.
*/
class @KWSYS_NAMESPACE@_EXPORT Glob
{
public:
Glob();
~Glob();
//! Find all files that match the pattern.
bool FindFiles(const std::string& inexpr);
//! Return the list of files that matched.
std::vector<std::string>& GetFiles();
//! Set recurse to true to match subdirectories.
void RecurseOn() { this->SetRecurse(true); }
void RecurseOff() { this->SetRecurse(false); }
void SetRecurse(bool i) { m_Recurse = i; }
bool GetRecurse() { return m_Recurse; }
protected:
//! Process directory
void ProcessDirectory(std::string::size_type start,
const std::string& dir, bool dir_only);
//! Process last directory, but only when recurse flags is on. That is
// effectively like saying: /path/to/file/**/file
void RecurseDirectory(std::string::size_type start,
const std::string& dir, bool dir_only);
//! Escape all non-alphanumeric characters in pattern.
void Escape(int ch, char* buffer);
//!
// Translate a shell PATTERN to a regular expression.
// There is no way to quote meta-characters.
std::string ConvertExpression(const std::string& expr);
//! Add regular expression
void AddExpression(const char* expr);
GlobInternals* m_Internals;
bool m_Recurse;
};
} // namespace @KWSYS_NAMESPACE@
#endif

View File

@ -75,11 +75,13 @@ KWSYS_C_SOURCES="\
KWSYS_CXX_SOURCES="\
Directory \
Glob \
RegularExpression \
SystemTools"
KWSYS_FILES="\
Directory.hxx \
Glob.hxx \
Process.h \
RegularExpression.hxx \
SystemTools.hxx"