82 #ifndef INCLUDED_SimpleGlob
83 #define INCLUDED_SimpleGlob
154 # include <mbstring.h>
155 # define sg_strchr ::_mbschr
156 # define sg_strrchr ::_mbsrchr
157 # define sg_strlen ::_mbslen
158 # if __STDC_WANT_SECURE_LIB__
159 # define sg_strcpy_s(a,n,b) ::_mbscpy_s(a,n,b)
161 # define sg_strcpy_s(a,n,b) ::_mbscpy(a,b)
163 # define sg_strcmp ::_mbscmp
164 # define sg_strcasecmp ::_mbsicmp
165 # define SOCHAR_T unsigned char
167 # include <sys/types.h>
168 # include <sys/stat.h>
171 # define MAX_PATH PATH_MAX
172 # define sg_strchr ::strchr
173 # define sg_strrchr ::strrchr
174 # define sg_strlen ::strlen
175 # define sg_strcpy_s(a,n,b) ::strcpy(a,b)
176 # define sg_strcmp ::strcmp
177 # define sg_strcasecmp ::strcasecmp
178 # define SOCHAR_T char
189 # define SG_ASSERT(b) _ASSERTE(b)
192 # define SG_ASSERT(b) assert(b)
195 # define SG_ASSERT(b)
201 static const char *
strchr(
const char *s,
char c) {
203 }
static const wchar_t *
strchr(
const wchar_t *s,
wchar_t c) {
204 return::wcschr(s, c);
207 static const char *
strrchr(
const char *s,
char c) {
210 static const wchar_t *
strrchr(
const wchar_t *s,
wchar_t c) {
211 return::wcsrchr(s, c);
222 static void strcpy_s(
char *dst,
size_t n,
const char *src) {
226 static void strcpy_s(
wchar_t *dst,
size_t n,
const wchar_t *src) {
227 # if __STDC_WANT_SECURE_LIB__
228 ::wcscpy_s(dst, n, src);
235 static int strcmp(
const char *s1,
const char *s2) {
238 static int strcmp(
const wchar_t *s1,
const wchar_t *s2) {
239 return::wcscmp(s1, s2);
246 static int strcasecmp(
const wchar_t *s1,
const wchar_t *s2) {
247 return::_wcsicmp(s1, s2);
260 #ifndef INVALID_FILE_ATTRIBUTES
261 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
264 #define SG_PATH_CHAR '\\'
270 m_hFind = FindFirstFileA(a_pszFileSpec, &m_oFindDataA);
271 if (m_hFind != INVALID_HANDLE_VALUE) {
274 DWORD dwErr = GetLastError();
275 if (dwErr == ERROR_FILE_NOT_FOUND) {
281 m_hFind = FindFirstFileW(a_pszFileSpec, &m_oFindDataW);
282 if (m_hFind != INVALID_HANDLE_VALUE) {
285 DWORD dwErr = GetLastError();
286 if (dwErr == ERROR_FILE_NOT_FOUND) {
293 return FindNextFileA(m_hFind, &m_oFindDataA) !=
FALSE;
296 return FindNextFileW(m_hFind, &m_oFindDataW) !=
FALSE;
304 return m_oFindDataA.cFileName;
307 return m_oFindDataW.cFileName;
312 bool IsDirS(
wchar_t)
const {
322 if (a_dwAttribs == INVALID_FILE_ATTRIBUTES) {
325 if (a_dwAttribs & FILE_ATTRIBUTE_DIRECTORY) {
333 WIN32_FIND_DATAA m_oFindDataA;
334 WIN32_FIND_DATAW m_oFindDataW;
339 #define SG_PATH_CHAR '/'
360 int nFlags = GLOB_MARK | GLOB_NOSORT;
365 nFlags |= GLOB_TILDE;
367 int rc = glob(a_pszFileSpec, nFlags, NULL, &
m_glob);
368 if (rc == GLOB_NOSPACE)
370 if (rc == GLOB_ABORTED)
372 if (rc == GLOB_NOMATCH)
404 if (0 != stat(a_pszPath, &sb)) {
407 if (S_ISDIR(sb.st_mode)) {
410 if (S_ISREG(sb.st_mode)) {
458 int Init(
unsigned int a_uiFlags = 0,
int a_nReservedSlots = 0);
473 int Add(
const SOCHAR * a_pszFileSpec);
489 int Add(
int a_nCount,
const SOCHAR *
const *a_rgpszFileSpec);
519 int AppendName(
const SOCHAR * a_pszFileName,
bool a_bIsDir);
554 Init(a_uiFlags, a_nReservedSlots);
567 m_nArgArrayType = POINTERS;
568 m_uiFlags = a_uiFlags;
569 m_nArgsLen = a_nReservedSlots;
570 m_nReservedSlots = a_nReservedSlots;
573 if (m_nReservedSlots > 0) {
574 if (!GrowArgvArray(m_nReservedSlots)) {
577 for (
int n = 0; n < m_nReservedSlots; ++n) {
598 a_pszFileSpec = szFileSpec;
602 m_szPathPrefix[0] = 0;
607 return AppendName(a_pszFileSpec,
false);
619 m_szPathPrefix[pszFilename - a_pszFileSpec + 1] = 0;
624 int rc = FindFirstFileS(a_pszFileSpec, m_uiFlags);
627 int ok = AppendName(a_pszFileSpec,
false);
634 int nError, nStartLen = m_nArgsLen;
637 nError = AppendName(GetFileNameS((SOCHAR) 0), IsDirS((SOCHAR) 0));
638 bSuccess = FindNextFileS((SOCHAR) 0);
646 nStartLen = m_nReservedSlots;
648 SetArgvArrayType(POINTERS);
649 qsort(m_rgpArgs + nStartLen, m_nArgsLen - nStartLen,
sizeof(m_rgpArgs[0]), fileSortCompare);
658 for (
int n = 0; n < a_nCount; ++n) {
659 nResult = Add(a_rgpszFileSpec[n]);
670 SetArgvArrayType(OFFSETS);
680 if (a_pszFileName[0] ==
'.') {
681 if (a_pszFileName[1] ==
'\0') {
684 if (a_pszFileName[1] ==
'.' && a_pszFileName[2] ==
'\0') {
690 if (!GrowArgvArray(m_nArgsLen + 1)) {
696 if (a_bIsDir && (m_uiFlags &
SG_GLOB_MARK) == SG_GLOB_MARK) {
699 if (!GrowStringBuffer(m_uiBufferLen + uiLen)) {
703 m_rgpArgs[m_nArgsLen++] = (SOCHAR *) m_uiBufferLen;
705 SimpleGlobUtil::strcpy_s(m_pBuffer + m_uiBufferLen + uiPrefixLen, m_uiBufferSize - m_uiBufferLen - uiPrefixLen, a_pszFileName);
706 m_uiBufferLen += uiLen;
709 if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) {
719 if (m_nArgArrayType == a_nNewType)
721 if (a_nNewType == POINTERS) {
723 for (
int n = 0; n < m_nArgsLen; ++n) {
724 m_rgpArgs[n] = (m_rgpArgs[n] == (SOCHAR *) - 1) ? NULL : m_pBuffer + (size_t) m_rgpArgs[n];
729 for (
int n = 0; n < m_nArgsLen; ++n) {
730 m_rgpArgs[n] = (m_rgpArgs[n] == NULL) ? (SOCHAR *) - 1 : (SOCHAR *) (m_rgpArgs[n] - m_pBuffer);
733 m_nArgArrayType = a_nNewType;
738 if (a_nNewLen >= m_nArgsSize) {
739 static const int SG_ARGV_INITIAL_SIZE = 32;
740 int nNewSize = (m_nArgsSize > 0) ? m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE;
741 while (a_nNewLen >= nNewSize) {
744 void *pNewBuffer = realloc(m_rgpArgs, nNewSize *
sizeof(SOCHAR *));
747 m_nArgsSize = nNewSize;
748 m_rgpArgs = (SOCHAR **) pNewBuffer;
755 if (a_uiMinSize >= m_uiBufferSize) {
756 static const int SG_BUFFER_INITIAL_SIZE = 1024;
757 size_t uiNewSize = (m_uiBufferSize > 0) ? m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE;
758 while (a_uiMinSize >= uiNewSize) {
761 void *pNewBuffer = realloc(m_pBuffer, uiNewSize *
sizeof(SOCHAR));
764 m_uiBufferSize = uiNewSize;
765 m_pBuffer = (SOCHAR *) pNewBuffer;
772 const SOCHAR *s1 = *(
const SOCHAR **) a1;
773 const SOCHAR *s2 = *(
const SOCHAR **) a2;
778 return s1 == s2 ? 0 : (s1 ? 1 : -1);
787 #if defined(_UNICODE)
788 # define CSimpleGlob CSimpleGlobW
790 # define CSimpleGlob CSimpleGlobA
793 #endif // INCLUDED_SimpleGlob
size_t m_uiBufferSize
allocated size of buffer
void SetArgvArrayType(ARG_ARRAY_TYPE a_nNewType)
Change the type of data stored in the argv array.
bool GrowStringBuffer(size_t a_uiMinSize)
Grow the string buffer to the required size.
Implementation of the SimpleGlob class.
~CSimpleGlobTempl()
Deallocate all memory buffers.
static size_t strlen(const char *s)
SG_Flags
The operation of SimpleGlob is fine-tuned via the use of a combination of the following flags...
int Add(const SOCHAR *a_pszFileSpec)
Add a new filespec to the glob.
SOCHAR ** Files()
Return the full argv array.
static const char * strrchr(const char *s, char c)
SOCHAR * m_pBuffer
argv string buffer
const char * GetFileNameS(char) const
bool GrowArgvArray(int a_nNewLen)
Grow the argv array to the required size.
static int strcasecmp(const char *s1, const char *s2)
#define sg_strcpy_s(a, n, b)
int m_nArgsSize
allocated size of array
static int strcmp(const char *s1, const char *s2)
static void strcpy_s(char *dst, size_t n, const char *src)
CSimpleGlobTempl< wchar_t > CSimpleGlobW
wchar_t version of CSimpleGlob
int Init(unsigned int a_uiFlags=0, int a_nReservedSlots=0)
Initialize (or re-initialize) the class in preparation for adding new filespecs.
ARG_ARRAY_TYPE
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.
String manipulation functions.
static void strcpy_s(wchar_t *dst, size_t n, const wchar_t *src)
static size_t strlen(const wchar_t *s)
static int fileSortCompare(const void *a1, const void *a2)
Compare two (possible NULL) strings.
CSimpleGlobTempl< char > CSimpleGlobA
ASCII/MBCS version of CSimpleGlob.
CSimpleGlobTempl(unsigned int a_uiFlags=0, int a_nReservedSlots=0)
Initialize the class.
static const char * strchr(const char *s, char c)
int m_nReservedSlots
number of client reserved slots in the argv array
int m_nArgsLen
used length
int FindFirstFileS(const char *a_pszFileSpec, unsigned int a_uiFlags)
SG_Error
Error return codes.
static int strcmp(const wchar_t *s1, const wchar_t *s2)
int AppendName(const SOCHAR *a_pszFileName, bool a_bIsDir)
Add a filename to the array if it passes all requirements.
size_t m_uiBufferLen
used length of buffer
int FileCount() const
Return the number of files in the argv array.
SOCHAR ** m_rgpArgs
argv array
static const wchar_t * strrchr(const wchar_t *s, wchar_t c)
SOCHAR m_szPathPrefix[MAX_PATH]
path prefix of any wildcard filenames
Unix glob implementation.
ARG_ARRAY_TYPE m_nArgArrayType
is the argv array storing indexes or pointers
SOCHAR * File(int n)
Return the a single file.
SG_FileType GetFileTypeS(const char *a_pszPath) const