CSimpleGlobTempl< SOCHAR > Class Template Reference

Implementation of the SimpleGlob class. More...

#include <SimpleGlob.h>

Inheritance diagram for CSimpleGlobTempl< SOCHAR >:

[legend]
Collaboration diagram for CSimpleGlobTempl< SOCHAR >:
[legend]

Public Member Functions

 CSimpleGlobTempl (unsigned int a_uiFlags=0, int a_nReservedSlots=0)
 Initialize the class.
 ~CSimpleGlobTempl ()
 Deallocate all memory buffers.
int Init (unsigned int a_uiFlags=0, int a_nReservedSlots=0)
 Initialize (or re-initialize) the class in preparation for adding new filespecs.
int Add (const SOCHAR *a_pszFileSpec)
 Add a new filespec to the glob.
int Add (int a_nCount, const SOCHAR *const *a_rgpszFileSpec)
 Add an array of filespec to the glob.
int FileCount () const
 Return the number of files in the argv array.
SOCHAR ** Files ()
 Return the full argv array.
SOCHAR * File (int n)
 Return the a single file.

Private Types

 OFFSETS
 POINTERS
enum  ARG_ARRAY_TYPE { OFFSETS, POINTERS }
 The argv array has it's members stored as either an offset into the string buffer, or as pointers to their string in the buffer. The offsets are used because if the string buffer is dynamically resized, all pointers into that buffer would become invalid. More...

Private Member Functions

void SetArgvArrayType (ARG_ARRAY_TYPE a_nNewType)
 Change the type of data stored in the argv array.
int AppendName (const SOCHAR *a_pszFileName, bool a_bIsDir)
 Add a filename to the array if it passes all requirements.
bool GrowArgvArray (int a_nNewLen)
 Grow the argv array to the required size.
bool GrowStringBuffer (size_t a_uiMinSize)
 Grow the string buffer to the required size.

Static Private Member Functions

static int fileSortCompare (const void *a1, const void *a2)
 Compare two (possible NULL) strings.

Private Attributes

unsigned int m_uiFlags
ARG_ARRAY_TYPE m_nArgArrayType
 is the argv array storing indexes or pointers
SOCHAR ** m_rgpArgs
 argv array
int m_nReservedSlots
 number of client reserved slots in the argv array
int m_nArgsSize
 allocated size of array
int m_nArgsLen
 used length
SOCHAR * m_pBuffer
 argv string buffer
size_t m_uiBufferSize
 allocated size of buffer
size_t m_uiBufferLen
 used length of buffer
SOCHAR m_szPathPrefix [MAX_PATH]
 path prefix of any wildcard filenames

Detailed Description

template<class SOCHAR>
class CSimpleGlobTempl< SOCHAR >

Implementation of the SimpleGlob class.

Definition at line 431 of file SimpleGlob.h.


Member Enumeration Documentation

template<class SOCHAR>
enum CSimpleGlobTempl::ARG_ARRAY_TYPE [private]

The argv array has it's members stored as either an offset into the string buffer, or as pointers to their string in the buffer. The offsets are used because if the string buffer is dynamically resized, all pointers into that buffer would become invalid.

Enumerator:
OFFSETS 
POINTERS 

Definition at line 513 of file SimpleGlob.h.

00513 { OFFSETS, POINTERS };


Constructor & Destructor Documentation

template<class SOCHAR>
CSimpleGlobTempl< SOCHAR >::CSimpleGlobTempl ( unsigned int  a_uiFlags = 0,
int  a_nReservedSlots = 0 
)

Initialize the class.

Parameters:
a_uiFlags Combination of SG_GLOB flags.
a_nReservedSlots Number of slots in the argv array that should be reserved. In the returned array these slots argv[0] ... argv[a_nReservedSlots-1] will be left empty for the caller to fill in.

Definition at line 547 of file SimpleGlob.h.

00548 {
00549         m_rgpArgs = NULL;
00550         m_nArgsSize = 0;
00551         m_pBuffer = NULL;
00552         m_uiBufferSize = 0;
00553 
00554         Init(a_uiFlags, a_nReservedSlots);
00555 }

template<class SOCHAR>
CSimpleGlobTempl< SOCHAR >::~CSimpleGlobTempl (  ) 

Deallocate all memory buffers.

Definition at line 557 of file SimpleGlob.h.

00558 {
00559         if (m_rgpArgs)
00560                 free(m_rgpArgs);
00561         if (m_pBuffer)
00562                 free(m_pBuffer);
00563 }


Member Function Documentation

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::Add ( int  a_nCount,
const SOCHAR *const *  a_rgpszFileSpec 
)

Add an array of filespec to the glob.

The filesystem will be immediately scanned for all matching files and directories in each filespec and they will be added to the glob.

Parameters:
a_nCount Number of filespec in the array.
a_rgpszFileSpec Array of filespec to add to the glob.
Returns:
SG_SUCCESS Matching files were added to the glob.

SG_ERR_NOMATCH Nothing matched the pattern. To ignore this error compare the return value to >= SG_SUCCESS.

SG_ERR_MEMORY Out of memory failure.

SG_ERR_FAILURE General failure.

Definition at line 655 of file SimpleGlob.h.

References SG_SUCCESS.

00656 {
00657         int nResult;
00658         for (int n = 0; n < a_nCount; ++n) {
00659                 nResult = Add(a_rgpszFileSpec[n]);
00660                 if (nResult != SG_SUCCESS) {
00661                         return nResult;
00662                 }
00663         }
00664         return SG_SUCCESS;
00665 }

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::Add ( const SOCHAR *  a_pszFileSpec  ) 

Add a new filespec to the glob.

The filesystem will be immediately scanned for all matching files and directories and they will be added to the glob.

Parameters:
a_pszFileSpec Filespec to add to the glob.
Returns:
SG_SUCCESS Matching files were added to the glob.

SG_ERR_NOMATCH Nothing matched the pattern. To ignore this error compare the return value to >= SG_SUCCESS.

SG_ERR_MEMORY Out of memory failure.

SG_ERR_FAILURE General failure.

Definition at line 585 of file SimpleGlob.h.

References MAX_PATH, SG_ERR_NOMATCH, SG_FILETYPE_DIR, SG_FILETYPE_INVALID, SG_GLOB_FULLSORT, SG_GLOB_NOCHECK, SG_GLOB_NOSORT, SG_PATH_CHAR, SG_SUCCESS, SimpleGlobUtil::strchr(), SimpleGlobUtil::strcpy_s(), and SimpleGlobUtil::strrchr().

00586 {
00587 #ifdef _WIN32
00588         // Windows FindFirst/FindNext recognizes forward slash as the same as backward slash
00589         // and follows the directories. We need to do the same when calculating the prefix
00590         // and when we have no wildcards.
00591         SOCHAR szFileSpec[MAX_PATH];
00592         SimpleGlobUtil::strcpy_s(szFileSpec, MAX_PATH, a_pszFileSpec);
00593         const SOCHAR *pszPath = SimpleGlobUtil::strchr(szFileSpec, '/');
00594         while (pszPath) {
00595                 szFileSpec[pszPath - szFileSpec] = SG_PATH_CHAR;
00596                 pszPath = SimpleGlobUtil::strchr(pszPath + 1, '/');
00597         }
00598         a_pszFileSpec = szFileSpec;
00599 #endif
00600 
00601         // if this doesn't contain wildcards then we can just add it directly
00602         m_szPathPrefix[0] = 0;
00603         if (!SimpleGlobUtil::strchr(a_pszFileSpec, '*') && !SimpleGlobUtil::strchr(a_pszFileSpec, '?')) {
00604                 SG_FileType nType = GetFileTypeS(a_pszFileSpec);
00605                 if (nType == SG_FILETYPE_INVALID) {
00606                         if (m_uiFlags & SG_GLOB_NOCHECK) {
00607                                 return AppendName(a_pszFileSpec, false);
00608                         }
00609                         return SG_ERR_NOMATCH;
00610                 }
00611                 return AppendName(a_pszFileSpec, nType == SG_FILETYPE_DIR);
00612         }
00613 #ifdef _WIN32
00614         // Windows doesn't return the directory with the filename, so we need to extract the
00615         // path from the search string ourselves and prefix it to the filename we get back.
00616         const SOCHAR *pszFilename = SimpleGlobUtil::strrchr(a_pszFileSpec, SG_PATH_CHAR);
00617         if (pszFilename) {
00618                 SimpleGlobUtil::strcpy_s(m_szPathPrefix, MAX_PATH, a_pszFileSpec);
00619                 m_szPathPrefix[pszFilename - a_pszFileSpec + 1] = 0;
00620         }
00621 #endif
00622 
00623         // search for the first match on the file
00624         int rc = FindFirstFileS(a_pszFileSpec, m_uiFlags);
00625         if (rc != SG_SUCCESS) {
00626                 if (rc == SG_ERR_NOMATCH && (m_uiFlags & SG_GLOB_NOCHECK)) {
00627                         int ok = AppendName(a_pszFileSpec, false);
00628                         if (ok != SG_SUCCESS)
00629                                 rc = ok;
00630                 }
00631                 return rc;
00632         }
00633         // add it and find all subsequent matches
00634         int nError, nStartLen = m_nArgsLen;
00635         bool bSuccess;
00636         do {
00637                 nError = AppendName(GetFileNameS((SOCHAR) 0), IsDirS((SOCHAR) 0));
00638                 bSuccess = FindNextFileS((SOCHAR) 0);
00639         }
00640         while (nError == SG_SUCCESS && bSuccess);
00641         SimpleGlobBase < SOCHAR >::FindDone();
00642 
00643         // sort these files if required
00644         if (m_nArgsLen > nStartLen && !(m_uiFlags & SG_GLOB_NOSORT)) {
00645                 if (m_uiFlags & SG_GLOB_FULLSORT) {
00646                         nStartLen = m_nReservedSlots;
00647                 }
00648                 SetArgvArrayType(POINTERS);
00649                 qsort(m_rgpArgs + nStartLen, m_nArgsLen - nStartLen, sizeof(m_rgpArgs[0]), fileSortCompare);
00650         }
00651 
00652         return nError;
00653 }

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::AppendName ( const SOCHAR *  a_pszFileName,
bool  a_bIsDir 
) [private]

Add a filename to the array if it passes all requirements.

Definition at line 667 of file SimpleGlob.h.

References SG_ERR_MEMORY, SG_GLOB_MARK, SG_GLOB_NODOT, SG_GLOB_ONLYDIR, SG_GLOB_ONLYFILE, SG_PATH_CHAR, SG_SUCCESS, SimpleGlobUtil::strcpy_s(), and SimpleGlobUtil::strlen().

00668 {
00669         // we need the argv array as offsets in case we resize it
00670         SetArgvArrayType(OFFSETS);
00671 
00672         // check for special cases which cause us to ignore this entry
00673         if ((m_uiFlags & SG_GLOB_ONLYDIR) && !a_bIsDir) {
00674                 return SG_SUCCESS;
00675         }
00676         if ((m_uiFlags & SG_GLOB_ONLYFILE) && a_bIsDir) {
00677                 return SG_SUCCESS;
00678         }
00679         if ((m_uiFlags & SG_GLOB_NODOT) && a_bIsDir) {
00680                 if (a_pszFileName[0] == '.') {
00681                         if (a_pszFileName[1] == '\0') {
00682                                 return SG_SUCCESS;
00683                         }
00684                         if (a_pszFileName[1] == '.' && a_pszFileName[2] == '\0') {
00685                                 return SG_SUCCESS;
00686                         }
00687                 }
00688         }
00689         // ensure that we have enough room in the argv array
00690         if (!GrowArgvArray(m_nArgsLen + 1)) {
00691                 return SG_ERR_MEMORY;
00692         }
00693         // ensure that we have enough room in the string buffer
00694         size_t uiPrefixLen = SimpleGlobUtil::strlen(m_szPathPrefix);
00695         size_t uiLen = uiPrefixLen + SimpleGlobUtil::strlen(a_pszFileName) + 1; // + null character
00696         if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) {
00697                 ++uiLen;                                // need space for the backslash
00698         }
00699         if (!GrowStringBuffer(m_uiBufferLen + uiLen)) {
00700                 return SG_ERR_MEMORY;
00701         }
00702         // add this entry
00703         m_rgpArgs[m_nArgsLen++] = (SOCHAR *) m_uiBufferLen;     // offset from beginning of buffer
00704         SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen, m_uiBufferSize - m_uiBufferLen, m_szPathPrefix);
00705         SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen + uiPrefixLen, m_uiBufferSize - m_uiBufferLen - uiPrefixLen, a_pszFileName);
00706         m_uiBufferLen += uiLen;
00707 
00708         // add the directory slash if desired
00709         if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) {
00710                 const static SOCHAR szDirSlash[] = { SG_PATH_CHAR, 0 };
00711                 SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen - 2, m_uiBufferSize - (m_uiBufferLen - 2), szDirSlash);
00712         }
00713 
00714         return SG_SUCCESS;
00715 }

template<class SOCHAR>
SOCHAR* CSimpleGlobTempl< SOCHAR >::File ( int  n  )  [inline]

Return the a single file.

Definition at line 502 of file SimpleGlob.h.

References CSimpleGlobTempl< SOCHAR >::Files(), CSimpleGlobTempl< SOCHAR >::m_nArgsLen, and SG_ASSERT.

00502                                    {
00503                 SG_ASSERT(n >= 0 && n < m_nArgsLen);
00504                 return Files()[n];
00505         }

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::FileCount (  )  const [inline]

Return the number of files in the argv array.

Definition at line 493 of file SimpleGlob.h.

References CSimpleGlobTempl< SOCHAR >::m_nArgsLen.

00493                                      {
00494                 return m_nArgsLen;
00495         }

template<class SOCHAR>
SOCHAR** CSimpleGlobTempl< SOCHAR >::Files (  )  [inline]

Return the full argv array.

Definition at line 496 of file SimpleGlob.h.

References CSimpleGlobTempl< SOCHAR >::m_rgpArgs, CSimpleGlobTempl< SOCHAR >::POINTERS, and CSimpleGlobTempl< SOCHAR >::SetArgvArrayType().

Referenced by CSimpleGlobTempl< SOCHAR >::File().

00496                                                                           {
00497                 SetArgvArrayType(POINTERS);
00498                 return m_rgpArgs;
00499         }

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::fileSortCompare ( const void *  a1,
const void *  a2 
) [static, private]

Compare two (possible NULL) strings.

Definition at line 770 of file SimpleGlob.h.

References SimpleGlobUtil::strcasecmp().

00771 {
00772         const SOCHAR *s1 = *(const SOCHAR **) a1;
00773         const SOCHAR *s2 = *(const SOCHAR **) a2;
00774         if (s1 && s2) {
00775                 return SimpleGlobUtil::strcasecmp(s1, s2);
00776         }
00777         // NULL sorts first
00778         return s1 == s2 ? 0 : (s1 ? 1 : -1);
00779 }

template<class SOCHAR>
bool CSimpleGlobTempl< SOCHAR >::GrowArgvArray ( int  a_nNewLen  )  [private]

Grow the argv array to the required size.

Definition at line 736 of file SimpleGlob.h.

00737 {
00738         if (a_nNewLen >= m_nArgsSize) {
00739                 static const int SG_ARGV_INITIAL_SIZE = 32;
00740                 int nNewSize = (m_nArgsSize > 0) ? m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE;
00741                 while (a_nNewLen >= nNewSize) {
00742                         nNewSize *= 2;
00743                 }
00744                 void *pNewBuffer = realloc(m_rgpArgs, nNewSize * sizeof(SOCHAR *));
00745                 if (!pNewBuffer)
00746                         return false;
00747                 m_nArgsSize = nNewSize;
00748                 m_rgpArgs = (SOCHAR **) pNewBuffer;
00749         }
00750         return true;
00751 }

template<class SOCHAR>
bool CSimpleGlobTempl< SOCHAR >::GrowStringBuffer ( size_t  a_uiMinSize  )  [private]

Grow the string buffer to the required size.

Definition at line 753 of file SimpleGlob.h.

00754 {
00755         if (a_uiMinSize >= m_uiBufferSize) {
00756                 static const int SG_BUFFER_INITIAL_SIZE = 1024;
00757                 size_t uiNewSize = (m_uiBufferSize > 0) ? m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE;
00758                 while (a_uiMinSize >= uiNewSize) {
00759                         uiNewSize *= 2;
00760                 }
00761                 void *pNewBuffer = realloc(m_pBuffer, uiNewSize * sizeof(SOCHAR));
00762                 if (!pNewBuffer)
00763                         return false;
00764                 m_uiBufferSize = uiNewSize;
00765                 m_pBuffer = (SOCHAR *) pNewBuffer;
00766         }
00767         return true;
00768 }

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::Init ( unsigned int  a_uiFlags = 0,
int  a_nReservedSlots = 0 
)

Initialize (or re-initialize) the class in preparation for adding new filespecs.

All existing files are cleared. Note that allocated memory is only deallocated at object destruction.

Parameters:
a_uiFlags Combination of SG_GLOB flags.
a_nReservedSlots Number of slots in the argv array that should be reserved. In the returned array these slots argv[0] ... argv[a_nReservedSlots-1] will be left empty for the caller to fill in.

Definition at line 565 of file SimpleGlob.h.

References SG_ERR_MEMORY, and SG_SUCCESS.

00566 {
00567         m_nArgArrayType = POINTERS;
00568         m_uiFlags = a_uiFlags;
00569         m_nArgsLen = a_nReservedSlots;
00570         m_nReservedSlots = a_nReservedSlots;
00571         m_uiBufferLen = 0;
00572 
00573         if (m_nReservedSlots > 0) {
00574                 if (!GrowArgvArray(m_nReservedSlots)) {
00575                         return SG_ERR_MEMORY;
00576                 }
00577                 for (int n = 0; n < m_nReservedSlots; ++n) {
00578                         m_rgpArgs[n] = NULL;
00579                 }
00580         }
00581 
00582         return SG_SUCCESS;
00583 }

template<class SOCHAR>
void CSimpleGlobTempl< SOCHAR >::SetArgvArrayType ( ARG_ARRAY_TYPE  a_nNewType  )  [private]

Change the type of data stored in the argv array.

Definition at line 717 of file SimpleGlob.h.

References SG_ASSERT.

Referenced by CSimpleGlobTempl< SOCHAR >::Files().

00718 {
00719         if (m_nArgArrayType == a_nNewType)
00720                 return;
00721         if (a_nNewType == POINTERS) {
00722                 SG_ASSERT(m_nArgArrayType == OFFSETS);
00723                 for (int n = 0; n < m_nArgsLen; ++n) {
00724                         m_rgpArgs[n] = (m_rgpArgs[n] == (SOCHAR *) - 1) ? NULL : m_pBuffer + (size_t) m_rgpArgs[n];
00725                 }
00726         } else {
00727                 SG_ASSERT(a_nNewType == OFFSETS);
00728                 SG_ASSERT(m_nArgArrayType == POINTERS);
00729                 for (int n = 0; n < m_nArgsLen; ++n) {
00730                         m_rgpArgs[n] = (m_rgpArgs[n] == NULL) ? (SOCHAR *) - 1 : (SOCHAR *) (m_rgpArgs[n] - m_pBuffer);
00731                 }
00732         }
00733         m_nArgArrayType = a_nNewType;
00734 }


Field Documentation

template<class SOCHAR>
ARG_ARRAY_TYPE CSimpleGlobTempl< SOCHAR >::m_nArgArrayType [private]

is the argv array storing indexes or pointers

Definition at line 532 of file SimpleGlob.h.

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::m_nArgsLen [private]

used length

Definition at line 536 of file SimpleGlob.h.

Referenced by CSimpleGlobTempl< SOCHAR >::File(), and CSimpleGlobTempl< SOCHAR >::FileCount().

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::m_nArgsSize [private]

allocated size of array

Definition at line 535 of file SimpleGlob.h.

template<class SOCHAR>
int CSimpleGlobTempl< SOCHAR >::m_nReservedSlots [private]

number of client reserved slots in the argv array

Definition at line 534 of file SimpleGlob.h.

template<class SOCHAR>
SOCHAR* CSimpleGlobTempl< SOCHAR >::m_pBuffer [private]

argv string buffer

Definition at line 537 of file SimpleGlob.h.

template<class SOCHAR>
SOCHAR** CSimpleGlobTempl< SOCHAR >::m_rgpArgs [private]

argv array

Definition at line 533 of file SimpleGlob.h.

Referenced by CSimpleGlobTempl< SOCHAR >::Files().

template<class SOCHAR>
SOCHAR CSimpleGlobTempl< SOCHAR >::m_szPathPrefix[MAX_PATH] [private]

path prefix of any wildcard filenames

Definition at line 540 of file SimpleGlob.h.

template<class SOCHAR>
size_t CSimpleGlobTempl< SOCHAR >::m_uiBufferLen [private]

used length of buffer

Definition at line 539 of file SimpleGlob.h.

template<class SOCHAR>
size_t CSimpleGlobTempl< SOCHAR >::m_uiBufferSize [private]

allocated size of buffer

Definition at line 538 of file SimpleGlob.h.

template<class SOCHAR>
unsigned int CSimpleGlobTempl< SOCHAR >::m_uiFlags [private]

Definition at line 531 of file SimpleGlob.h.


The documentation for this class was generated from the following file:
Generated on Wed May 16 04:00:21 2012 for FreeSWITCH API Documentation by  doxygen 1.4.7