KiCad PCB EDA Suite
common.h File Reference

The common library. More...

#include <vector>
#include <functional>
#include <wx/confbase.h>
#include <wx/fileconf.h>
#include <wx/dir.h>
#include <wx/string.h>
#include <wx/gdicmn.h>
#include <wx/process.h>
#include <atomic>
#include <limits>
#include <memory>
#include <type_traits>
#include <typeinfo>
#include <macros.h>

Go to the source code of this file.

Classes

struct  std::hash< wxString >
 
struct  std::hash< wxPoint >
 
struct  std::less< wxPoint >
 

Namespaces

 std
 

Macros

#define USE_KICAD_WXSTRING_HASH
 Template specialization to enable wxStrings for certain containers (e.g. unordered_map) More...
 
#define USE_KICAD_WXPOINT_LESS_AND_HASH
 Required to use wxPoint as key type in maps. More...
 

Functions

int ProcessExecute (const wxString &aCommandLine, int aFlags=wxEXEC_ASYNC, wxProcess *callback=nullptr)
 Run a command in a child process. More...
 
wxString SearchHelpFileFullPath (const SEARCH_STACK &aSearchStack, const wxString &aBaseName)
 Return the help file's full path. More...
 
bool EnsureFileDirectoryExists (wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter=nullptr)
 Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist. More...
 
const wxString ExpandEnvVarSubstitutions (const wxString &aString, PROJECT *aProject)
 Replace any environment variable & text variable references with their values. More...
 
wxString ExpandTextVars (const wxString &aSource, const std::function< bool(wxString *)> *aLocalResolver, const std::function< bool(wxString *)> *aFallbackResolver, const PROJECT *aProject)
 Expand '${var-name}' templates in text. More...
 
wxString ExpandTextVars (const wxString &aSource, const PROJECT *aProject)
 
const wxString ResolveUriByEnvVars (const wxString &aUri, PROJECT *aProject)
 Replace any environment and/or text variables in file-path uris (leaving network-path URIs alone). More...
 
std::ostream & operator<< (std::ostream &out, const wxSize &size)
 Helper function to print the given wxSize to a stream. More...
 
std::ostream & operator<< (std::ostream &out, const wxPoint &pt)
 Helper function to print the given wxPoint to a stream. More...
 
long long TimestampDir (const wxString &aDirPath, const wxString &aFilespec)
 A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/filename.cpp. More...
 

Detailed Description

The common library.

Definition in file common.h.

Macro Definition Documentation

◆ USE_KICAD_WXPOINT_LESS_AND_HASH

#define USE_KICAD_WXPOINT_LESS_AND_HASH

Required to use wxPoint as key type in maps.

Definition at line 142 of file common.h.

◆ USE_KICAD_WXSTRING_HASH

#define USE_KICAD_WXSTRING_HASH

Template specialization to enable wxStrings for certain containers (e.g. unordered_map)

Definition at line 130 of file common.h.

Function Documentation

◆ EnsureFileDirectoryExists()

bool EnsureFileDirectoryExists ( wxFileName *  aTargetFullFileName,
const wxString &  aBaseFilename,
REPORTER aReporter = nullptr 
)

Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.

Parameters
aTargetFullFileNamethe wxFileName containing the full path and file name to modify. The path may be absolute or relative to aBaseFilename .
aBaseFilenamea full filename. Only its path is used to set the aTargetFullFileName path.
aReportera point to a REPORTER object use to show messages (can be NULL)
Returns
true if aOutputDir already exists or was successfully created.

Definition at line 297 of file common.cpp.

300 {
301  wxString msg;
302  wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
303 
304  // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
305  // already an absolute path) absolute:
306  if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
307  {
308  if( aReporter )
309  {
310  msg.Printf( _( "Cannot make path \"%s\" absolute with respect to \"%s\"." ),
311  aTargetFullFileName->GetPath(),
312  baseFilePath );
313  aReporter->Report( msg, RPT_SEVERITY_ERROR );
314  }
315 
316  return false;
317  }
318 
319  // Ensure the path of aTargetFullFileName exists, and create it if needed:
320  wxString outputPath( aTargetFullFileName->GetPath() );
321 
322  if( !wxFileName::DirExists( outputPath ) )
323  {
324  // Make every directory provided when the provided path doesn't exist
325  if( wxFileName::Mkdir( outputPath, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
326  {
327  if( aReporter )
328  {
329  msg.Printf( _( "Output directory \"%s\" created.\n" ), outputPath );
330  aReporter->Report( msg, RPT_SEVERITY_INFO );
331  return true;
332  }
333  }
334  else
335  {
336  if( aReporter )
337  {
338  msg.Printf( _( "Cannot create output directory \"%s\".\n" ), outputPath );
339  aReporter->Report( msg, RPT_SEVERITY_ERROR );
340  }
341 
342  return false;
343  }
344  }
345 
346  return true;
347 }
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
#define _(s)
Definition: 3d_actions.cpp:33

References _, REPORTER::Report(), RPT_SEVERITY_ERROR, and RPT_SEVERITY_INFO.

Referenced by DIALOG_GEN_FOOTPRINT_POSITION::CreateAsciiFiles(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), DIALOG_PLOT_SCHEMATIC::createPlotFileName(), DIALOG_EXPORT_SVG::ExportSVGFile(), DIALOG_GENDRILL::GenDrillAndMapFiles(), PLOT_CONTROLLER::OpenPlotfile(), and DIALOG_PLOT::Plot().

◆ ExpandEnvVarSubstitutions()

const wxString ExpandEnvVarSubstitutions ( const wxString &  aString,
PROJECT aProject 
)

Replace any environment variable & text variable references with their values.

Parameters
aStringa string containing (perhaps) references to env var
Returns
the expanded environment variable.

Definition at line 269 of file common.cpp.

270 {
271  // wxGetenv( wchar_t* ) is not re-entrant on linux.
272  // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
273  static std::mutex getenv_mutex;
274 
275  std::lock_guard<std::mutex> lock( getenv_mutex );
276 
277  // We reserve the right to do this another way, by providing our own member function.
278  return KIwxExpandEnvVars( aString, aProject );
279 }
wxString KIwxExpandEnvVars(const wxString &str, const PROJECT *aProject)
Definition: common.cpp:122

References KIwxExpandEnvVars().

Referenced by FILENAME_RESOLVER::addPath(), FILENAME_RESOLVER::checkEnvVarPath(), S3D_PLUGIN_MANAGER::checkPluginName(), S3D_PLUGIN_MANAGER::checkPluginPath(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), FILENAME_RESOLVER::createPathList(), DIALOG_PLOT_SCHEMATIC::createPlotFileName(), DIALOG_EXPORT_SVG::ExportSVGFile(), DIALOG_GENDRILL::GenDrillAndMapFiles(), LIB_TABLE_ROW::GetFullURI(), DS_DATA_MODEL::MakeFullFileName(), TEXT_BUTTON_FILE_BROWSER::OnButtonClick(), PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries(), DIALOG_GENDRILL::OnGenReportFile(), DIALOG_EXPORT_SVG::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT::OnOutputDirectoryBrowseClicked(), DIALOG_GEN_FOOTPRINT_POSITION::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT_SCHEMATIC::OnOutputDirectoryBrowseClicked(), DIALOG_GENDRILL::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT::Plot(), FILENAME_RESOLVER::ResolvePath(), ResolveUriByEnvVars(), FILENAME_RESOLVER::Set3DConfigDir(), S3D_CACHE::Set3DConfigDir(), FILENAME_RESOLVER::SetProject(), FILENAME_RESOLVER::ShortenPath(), and ERC_TESTER::TestTextVars().

◆ ExpandTextVars() [1/2]

wxString ExpandTextVars ( const wxString &  aSource,
const std::function< bool(wxString *)> *  aLocalResolver,
const std::function< bool(wxString *)> *  aFallbackResolver,
const PROJECT aProject 
)

Expand '${var-name}' templates in text.

The LocalResolver is given first crack at it, after which the PROJECT's resolver is called.

Definition at line 64 of file common.cpp.

68 {
69  wxString newbuf;
70  size_t sourceLen = aSource.length();
71 
72  newbuf.Alloc( sourceLen ); // best guess (improves performance)
73 
74  for( size_t i = 0; i < sourceLen; ++i )
75  {
76  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
77  {
78  wxString token;
79 
80  for( i = i + 2; i < sourceLen; ++i )
81  {
82  if( aSource[i] == '}' )
83  break;
84  else
85  token.append( aSource[i] );
86  }
87 
88  if( token.IsEmpty() )
89  continue;
90 
91  if( aLocalResolver && (*aLocalResolver)( &token ) )
92  {
93  newbuf.append( token );
94  }
95  else if( aProject && aProject->TextVarResolver( &token ) )
96  {
97  newbuf.append( token );
98  }
99  else if( aFallbackResolver && (*aFallbackResolver)( &token ) )
100  {
101  newbuf.append( token );
102  }
103  else
104  {
105  // Token not resolved: leave the reference unchanged
106  newbuf.append( "${" + token + "}" );
107  }
108  }
109  else
110  {
111  newbuf.append( aSource[i] );
112  }
113  }
114 
115  return newbuf;
116 }
virtual bool TextVarResolver(wxString *aToken) const

References PROJECT::TextVarResolver().

◆ ExpandTextVars() [2/2]

wxString ExpandTextVars ( const wxString &  aSource,
const PROJECT aProject 
)

Definition at line 58 of file common.cpp.

59 {
60  return ExpandTextVars( aSource, nullptr, nullptr, aProject );
61 }
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:58

References ExpandTextVars().

Referenced by AddGerberX2Header(), DS_DRAW_ITEM_LIST::BuildFullText(), ExpandTextVars(), PCB_TEXT::GetShownText(), SCH_FIELD::GetShownText(), SCH_TEXT::GetShownText(), FP_TEXT::GetShownText(), NETLIST_EXPORTER_XML::makeDesignHeader(), ResolveUriByEnvVars(), and TITLE_BLOCK::TextVarResolver().

◆ operator<<() [1/2]

std::ostream& operator<< ( std::ostream &  out,
const wxSize &  size 
)

Helper function to print the given wxSize to a stream.

Used for debugging functions like EDA_ITEM::Show and also in unit testing fixtures.

Definition at line 379 of file common.cpp.

380 {
381  out << " width=\"" << size.GetWidth() << "\" height=\"" << size.GetHeight() << "\"";
382  return out;
383 }

◆ operator<<() [2/2]

std::ostream& operator<< ( std::ostream &  out,
const wxPoint &  pt 
)

Helper function to print the given wxPoint to a stream.

Used for debugging functions like EDA_ITEM::Show and also in unit testing fixtures.

Definition at line 386 of file common.cpp.

387 {
388  out << " x=\"" << pt.x << "\" y=\"" << pt.y << "\"";
389  return out;
390 }

◆ ProcessExecute()

int ProcessExecute ( const wxString &  aCommandLine,
int  aFlags = wxEXEC_ASYNC,
wxProcess *  callback = nullptr 
)

Run a command in a child process.

Parameters
aCommandLineThe process and any arguments to it all in a single string.
aFlagsThe same args as allowed for wxExecute()
callbackwxProcess implementing OnTerminate to be run when the child process finishes
Returns
pid of process, 0 in case of error (like return values of wxExecute()).

Definition at line 40 of file common.cpp.

41 {
42  return (int) wxExecute( aCommandLine, aFlags, callback );
43 }

Referenced by doPrintFile(), ExecuteFile(), GetAssociatedDocument(), OpenFile(), OpenPDF(), and SCH_EDIT_FRAME::WriteNetListFile().

◆ ResolveUriByEnvVars()

const wxString ResolveUriByEnvVars ( const wxString &  aUri,
PROJECT aProject 
)

Replace any environment and/or text variables in file-path uris (leaving network-path URIs alone).

Definition at line 282 of file common.cpp.

283 {
284  wxString uri = ExpandTextVars( aUri, aProject );
285 
286  // URL-like URI: return as is.
287  wxURL url( uri );
288 
289  if( url.GetError() == wxURL_NOERR )
290  return uri;
291 
292  // Otherwise, the path points to a local file. Resolve environment variables if any.
293  return ExpandEnvVarSubstitutions( aUri, aProject );
294 }
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:58
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:269

References ExpandEnvVarSubstitutions(), and ExpandTextVars().

Referenced by GetAssociatedDocument().

◆ SearchHelpFileFullPath()

wxString SearchHelpFileFullPath ( const SEARCH_STACK aSearchStack,
const wxString &  aBaseName 
)

Return the help file's full path.

Return the KiCad help file with path and extension. Help files can be html (.html ext) or pdf (.pdf ext) files. A <BaseName>.html file is searched and if not found, <BaseName>.pdf file is searched in the same path. If the help file for the current locale is not found, an attempt to find the English version of the help file is made. Help file is searched in directories in this order: help/<canonical name> like help/en_GB help/<short name> like help/en help/en

Parameters
aSearchStackcontains some possible base dirs that may be above the the one actually holding aBaseName. These are starting points for nested searches.
aBaseNameis the name of the help file to search for,

without extension

.

Returns
wxEmptyString is returned if aBaseName is not found, else the full path & filename.

Definition at line 69 of file searchhelpfilefullpath.cpp.

70 {
71  wxArrayString subdirs;
72  wxArrayString altsubdirs;
73  SEARCH_STACK ss = aSStack;
74 
75  // It might already be in aSStack, but why depend on other code
76  // far away when it's so easy to add it again (to our copy) as the first place to look.
77 
78  // This is CMAKE_INSTALL_PREFIX unless DEFAULT_INSTALL_PATH was defined during
79  // build configuration:
80  ss.AddPaths( wxT( DEFAULT_INSTALL_PATH ), 0 );
81 
82 #if defined(__WXMAC__)
83  ss.AddPaths( PATHS::GetOSXKicadMachineDataDir() );
84  ss.AddPaths( Pgm().GetExecutablePath(), 0 );
85 
86  // OS X packages can have the help files in
87  // /Library/Application\ Support/kicad/help,
88  // and in Contents/SharedSupport/help inside the
89  // bundle.
90  // Below we account for an international subdirectory.
91  subdirs.Add( "help" );
92  altsubdirs.Add( "Contents" );
93  altsubdirs.Add( "SharedSupport" );
94  altsubdirs.Add( "help" );
95 #endif
96 
97 #if ! defined(__WXMAC__) // && defined(__linux__)
98  // This is the executable path minus the trailing bin directory used on Windows and Linux.
99  wxFileName tmp( Pgm().GetExecutablePath(), wxEmptyString );
100  wxArrayString binDirs = tmp.GetDirs();
101 
102  if( !binDirs.IsEmpty() && binDirs[ binDirs.GetCount() - 1 ].CmpNoCase( wxT( "bin" ) ) == 0 )
103  tmp.RemoveLastDir();
104 
105  ss.AddPaths( tmp.GetPath(), 0 );
106 
107  // Based on kicad-doc.bzr/CMakeLists.txt, line 20, the help files are
108  // installed into "<CMAKE_INSTALL_PREFIX>/share/doc/kicad/help" for linux.
109  // This is ${KICAD_HELP} var in that CMakeLists.txt file.
110  // Below we account for an international subdirectory.
111  subdirs.Add( "share" );
112  subdirs.Add( "doc" );
113  subdirs.Add( "kicad" );
114  subdirs.Add( "help" );
115 
116  // Based on kicad-doc.bzr/CMakeLists.txt, line 35, the help files are
117  // installed into "<CMAKE_INSTALL_PREFIX>/doc/help" for Windows.
118  // This is ${KICAD_HELP} var in that CMakeLists.txt file.
119  // Below we account for an international subdirectory.
120  altsubdirs.Add( "doc" );
121  altsubdirs.Add( "help" );
122 #endif
123 
124  // If there's a KICAD environment variable set, always use that guy's path first.
125  if( !Pgm().GetKicadEnvVariable().IsEmpty() )
126  ss.AddPaths( Pgm().GetKicadEnvVariable(), 0 );
127 
128  /* Search for a help file.
129  * we *must* find a help file.
130  * so help is searched in directories in this order:
131  * help/<canonical name> like help/en_GB
132  * help/<short name> like help/en
133  * help/en
134  */
135 
136  wxLocale* i18n = Pgm().GetLocale();
137 
138  // We try to find help file in help/<canonical name>
139  // If fails, try to find help file in help/<short canonical name>
140  // If fails, try to find help file in help/en
141  wxArrayString locale_name_dirs;
142  locale_name_dirs.Add( i18n->GetCanonicalName() ); // canonical name like fr_FR
143 
144  // wxLocale::GetName() does not return always the short name
145  locale_name_dirs.Add( i18n->GetName().BeforeLast( '_' ) ); // short canonical name like fr
146  locale_name_dirs.Add( "en" ); // default (en)
147 
148 #if defined(DEBUG) && 1
149  ss.Show( wxString( __func__ ) );
150  wxLogTrace( tracePathsAndFiles, "%s: m_help_file:'%s'", __func__, aBaseName );
151 #endif
152 
153  wxLogTrace( tracePathsAndFiles, "Checking SEARCH_STACK for file %s", aBaseName );
154 
155  // Help files can be html (.html ext) or pdf (.pdf ext) files.
156  // Therefore, <BaseName>.html file is searched and if not found,
157  // <BaseName>.pdf file is searched in the same paths
158  wxString fn;
159 
160  for( unsigned ii = 0; ii < locale_name_dirs.GetCount(); ii++ )
161  {
162  subdirs.Add( locale_name_dirs[ii] );
163  altsubdirs.Add( locale_name_dirs[ii] );
164 
165  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".html" ), &altsubdirs );
166 
167  if( !fn.IsEmpty() )
168  {
169  // Prepend URI protocol since we will open in a browser
170  fn = wxT( "file://" ) + fn;
171  break;
172  }
173 
174  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".pdf" ), &altsubdirs );
175 
176  if( !fn.IsEmpty() )
177  break;
178 
179  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".html" ), &subdirs );
180 
181  if( !fn.IsEmpty() )
182  {
183  // Prepend URI protocol since we will open in a browser
184  fn = wxT( "file://" ) + fn;
185  break;
186  }
187 
188  fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".pdf" ), &subdirs );
189 
190  if( !fn.IsEmpty() )
191  break;
192 
193  subdirs.RemoveAt( subdirs.GetCount() - 1 );
194  altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 );
195  }
196 
197  return fn;
198 }
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
Look for files in a number of paths.
Definition: search_stack.h:41
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
wxString FindFileInSearchPaths(const SEARCH_STACK &aStack, const wxString &aFilename, const wxArrayString *aSubdirs)
Function FindFileInSearchPaths looks in "this" for aFilename, but first modifies every search path by...
void AddPaths(const wxString &aPaths, int aIndex=-1)
Insert or append path(s).

References SEARCH_STACK::AddPaths(), FindFileInSearchPaths(), Pgm(), and tracePathsAndFiles.

Referenced by COMMON_CONTROL::ShowHelp().

◆ TimestampDir()

long long TimestampDir ( const wxString &  aDirPath,
const wxString &  aFilespec 
)

A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/filename.cpp.

TimestampDir

This routine offers SIGNIFICANT performance benefits over using wxWidgets to gather timestamps from matching files in a directory.

Parameters
aDirPaththe directory to search
aFilespeca (wildcarded) file spec to match against
Returns
a hash of the last-mod-dates of all matching files in the directory

Definition at line 549 of file common.cpp.

550 {
551  long long timestamp = 0;
552 
553 #if defined( __WIN32__ )
554  // Win32 version.
555  // Save time by not searching for each path twice: once in wxDir.GetNext() and once in
556  // wxFileName.GetModificationTime(). Also cuts out wxWidgets' string-matching and case
557  // conversion by staying on the MSW side of things.
558  std::wstring filespec( aDirPath.t_str() );
559  filespec += '\\';
560  filespec += aFilespec.t_str();
561 
562  WIN32_FIND_DATA findData;
563  wxDateTime lastModDate;
564 
565  HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
566 
567  if( fileHandle != INVALID_HANDLE_VALUE )
568  {
569  do
570  {
571  ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
572  timestamp += lastModDate.GetValue().GetValue();
573  timestamp += findData.nFileSizeLow; // Get the file size (partial) as well to check for sneaky changes
574  }
575  while ( FindNextFile( fileHandle, &findData ) != 0 );
576  }
577 
578  FindClose( fileHandle );
579 #else
580  // POSIX version.
581  // Save time by not converting between encodings -- do everything on the file-system side.
582  std::string filespec( aFilespec.fn_str() );
583  std::string dir_path( aDirPath.fn_str() );
584 
585  DIR* dir = opendir( dir_path.c_str() );
586 
587  if( dir )
588  {
589  for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
590  {
591  if( !matchWild( filespec.c_str(), dir_entry->d_name, true ) )
592  continue;
593 
594  std::string entry_path = dir_path + '/' + dir_entry->d_name;
595  struct stat entry_stat;
596 
597  if( wxCRT_Lstat( entry_path.c_str(), &entry_stat ) == 0 )
598  {
599  // Timestamp the source file, not the symlink
600  if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
601  {
602  char buffer[ PATH_MAX + 1 ];
603  ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
604 
605  if( pathLen > 0 )
606  {
607  struct stat linked_stat;
608  buffer[ pathLen ] = '\0';
609  entry_path = dir_path + buffer;
610 
611  if( wxCRT_Lstat( entry_path.c_str(), &linked_stat ) == 0 )
612  {
613  entry_stat = linked_stat;
614  }
615  else
616  {
617  // if we couldn't lstat the linked file we'll have to just use
618  // the symbolic link info
619  }
620  }
621  }
622 
623  if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists()
624  {
625  timestamp += entry_stat.st_mtime * 1000;
626  timestamp += entry_stat.st_size; // Get the file size as well to check for sneaky changes
627  }
628  }
629  else
630  {
631  // if we couldn't lstat the file itself all we can do is use the name
632  timestamp += (signed) std::hash<std::string>{}( std::string( dir_entry->d_name ) );
633  }
634  }
635 
636  closedir( dir );
637  }
638 #endif
639 
640  return timestamp;
641 }
bool matchWild(const char *pat, const char *text, bool dot_special)
Performance enhancements to file and directory operations.
Definition: common.cpp:407

References matchWild().

Referenced by FP_CACHE::GetTimestamp(), and GPCB_FPL_CACHE::GetTimestamp().