#include <SimpleGlob.h>
Inheritance diagram for CSimpleGlobTempl< SOCHAR >:
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 | |
Definition at line 431 of file SimpleGlob.h.
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.
Definition at line 513 of file SimpleGlob.h.
| CSimpleGlobTempl< SOCHAR >::CSimpleGlobTempl | ( | unsigned int | a_uiFlags = 0, |
|
| int | a_nReservedSlots = 0 | |||
| ) |
Initialize the class.
| 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 }
| CSimpleGlobTempl< SOCHAR >::~CSimpleGlobTempl | ( | ) |
| 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.
| a_nCount | Number of filespec in the array. | |
| a_rgpszFileSpec | Array of filespec to add 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 }
| 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.
| a_pszFileSpec | Filespec to add 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 }
| 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 }
| 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 }
| 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 }
| 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 }
| 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 }
| 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 }
| 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 }
| 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.
| 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 }
| 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 }
ARG_ARRAY_TYPE CSimpleGlobTempl< SOCHAR >::m_nArgArrayType [private] |
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().
int CSimpleGlobTempl< SOCHAR >::m_nArgsSize [private] |
int CSimpleGlobTempl< SOCHAR >::m_nReservedSlots [private] |
SOCHAR* CSimpleGlobTempl< SOCHAR >::m_pBuffer [private] |
SOCHAR** CSimpleGlobTempl< SOCHAR >::m_rgpArgs [private] |
argv array
Definition at line 533 of file SimpleGlob.h.
Referenced by CSimpleGlobTempl< SOCHAR >::Files().
SOCHAR CSimpleGlobTempl< SOCHAR >::m_szPathPrefix[MAX_PATH] [private] |
size_t CSimpleGlobTempl< SOCHAR >::m_uiBufferLen [private] |
size_t CSimpleGlobTempl< SOCHAR >::m_uiBufferSize [private] |
unsigned int CSimpleGlobTempl< SOCHAR >::m_uiFlags [private] |
Definition at line 531 of file SimpleGlob.h.
1.4.7