83 #ifndef INCLUDED_SimpleGlob
84 #define INCLUDED_SimpleGlob
155 # if !defined(_WIN32) && defined(USTRING_H)
156 # define SG_HAVE_ICU 1
158 # define SG_HAVE_ICU 0
168 # include <mbstring.h>
169 # define sg_strchr ::_mbschr
170 # define sg_strrchr ::_mbsrchr
171 # define sg_strlen ::_mbslen
172 # if __STDC_WANT_SECURE_LIB__
173 # define sg_strcpy_s(a,n,b) ::_mbscpy_s(a,n,b)
175 # define sg_strcpy_s(a,n,b) ::_mbscpy(a,b)
177 # define sg_strcmp ::_mbscmp
178 # define sg_strcasecmp ::_mbsicmp
179 # define SOCHAR_T unsigned char
181 # include <sys/types.h>
182 # include <sys/stat.h>
185 # define MAX_PATH PATH_MAX
186 # define sg_strchr ::strchr
187 # define sg_strrchr ::strrchr
188 # define sg_strlen ::strlen
189 # define sg_strcpy_s(a,n,b) ::strcpy(a,b)
190 # define sg_strcmp ::strcmp
191 # define sg_strcasecmp ::strcasecmp
192 # define SOCHAR_T char
203 # define SG_ASSERT(b) _ASSERTE(b)
206 # define SG_ASSERT(b) assert(b)
209 # define SG_ASSERT(b)
216 static const char *
strchr(
const char *s,
char c) {
219 static const wchar_t *
strchr(
const wchar_t *s,
wchar_t c) {
220 return ::wcschr(s, c);
223 static const UChar *
strchr(
const UChar *s, UChar c) {
224 return ::u_strchr(s, c);
228 static const char *
strrchr(
const char *s,
char c) {
231 static const wchar_t *
strrchr(
const wchar_t *s,
wchar_t c) {
232 return ::wcsrchr(s, c);
235 static const UChar *
strrchr(
const UChar *s, UChar c) {
236 return ::u_strrchr(s, c);
241 static size_t strlen(
const char *s) { return ::strlen(s); }
242 static size_t strlen(
const wchar_t *s) { return ::wcslen(s); }
244 static size_t strlen(
const UChar *s) { return ::u_strlen(s); }
247 static void strcpy_s(
char *dst,
size_t n,
const char *src) {
251 static void strcpy_s(
wchar_t *dst,
size_t n,
const wchar_t *src) {
252 # if __STDC_WANT_SECURE_LIB__
253 ::wcscpy_s(dst, n, src);
260 static void strcpy_s(UChar *dst,
size_t n,
const UChar *src) {
261 ::u_strncpy(dst, src, n);
265 static int strcmp(
const char *s1,
const char *s2) {
268 static int strcmp(
const wchar_t *s1,
const wchar_t *s2) {
269 return ::wcscmp(s1, s2);
272 static int strcmp(
const UChar *s1,
const UChar *s2) {
273 return ::u_strcmp(s1, s2);
281 static int strcasecmp(
const wchar_t *s1,
const wchar_t *s2) {
282 return ::_wcsicmp(s1, s2);
286 static int strcasecmp(
const UChar *s1,
const UChar *s2) {
287 return u_strcasecmp(s1, s2, 0);
300 #ifndef INVALID_FILE_ATTRIBUTES
301 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
304 #define SG_PATH_CHAR '\\'
307 template<
class SOCHAR>
313 m_hFind = FindFirstFileA(a_pszFileSpec, &m_oFindDataA);
314 if (m_hFind != INVALID_HANDLE_VALUE) {
317 DWORD dwErr = GetLastError();
318 if (dwErr == ERROR_FILE_NOT_FOUND) {
324 m_hFind = FindFirstFileW(a_pszFileSpec, &m_oFindDataW);
325 if (m_hFind != INVALID_HANDLE_VALUE) {
328 DWORD dwErr = GetLastError();
329 if (dwErr == ERROR_FILE_NOT_FOUND) {
336 return FindNextFileA(m_hFind, &m_oFindDataA) != FALSE;
339 return FindNextFileW(m_hFind, &m_oFindDataW) != FALSE;
347 return m_oFindDataA.cFileName;
350 return m_oFindDataW.cFileName;
356 bool IsDirS(
wchar_t)
const {
361 return this->
GetFileTypeS(GetFileAttributesA(a_pszPath));
364 return this->
GetFileTypeS(GetFileAttributesW(a_pszPath));
367 if (a_dwAttribs == INVALID_FILE_ATTRIBUTES) {
370 if (a_dwAttribs & FILE_ATTRIBUTE_DIRECTORY) {
378 WIN32_FIND_DATAA m_oFindDataA;
379 WIN32_FIND_DATAW m_oFindDataW;
384 #define SG_PATH_CHAR '/'
387 template<
class SOCHAR>
391 memset(&m_glob, 0,
sizeof(m_glob));
392 m_uiCurr = (size_t)-1;
401 size_t len = strlen(m_glob.gl_pathv[m_uiCurr]);
402 if (m_glob.gl_pathv[m_uiCurr][len-1] ==
'/') {
404 m_glob.gl_pathv[m_uiCurr][len-1] = 0;
409 int nFlags = GLOB_MARK | GLOB_NOSORT;
412 int rc = glob(a_pszFileSpec, nFlags, NULL, &m_glob);
422 int FindFirstFileS(
const UChar * a_pszFileSpec,
unsigned int a_uiFlags) {
423 char buf[PATH_MAX] = { 0 };
424 UErrorCode status = U_ZERO_ERROR;
425 u_strToUTF8(
buf,
sizeof(
buf), NULL, a_pszFileSpec, -1, &status);
433 if (++m_uiCurr >= m_glob.gl_pathc) {
448 memset(&m_glob, 0,
sizeof(m_glob));
449 m_uiCurr = (size_t)-1;
454 return m_glob.gl_pathv[m_uiCurr];
460 if (!pszFile)
return NULL;
461 UErrorCode status = U_ZERO_ERROR;
462 memset(m_szBuf, 0,
sizeof(m_szBuf));
463 u_strFromUTF8(m_szBuf, PATH_MAX, NULL, pszFile, -1, &status);
464 if (U_FAILURE(status))
return NULL;
475 bool IsDirS(UChar)
const {
476 return this->
IsDirS((
char)0);
482 if (0 != stat(a_pszPath, &sb)) {
485 if (S_ISDIR(sb.st_mode)) {
488 if (S_ISREG(sb.st_mode)) {
496 char buf[PATH_MAX] = { 0 };
497 UErrorCode status = U_ZERO_ERROR;
498 u_strToUTF8(
buf,
sizeof(
buf), NULL, a_pszPath, -1, &status);
509 mutable UChar m_szBuf[PATH_MAX];
522 template<
class SOCHAR>
551 int Init(
unsigned int a_uiFlags = 0,
int a_nReservedSlots = 0);
566 int Add(
const SOCHAR *a_pszFileSpec);
582 int Add(
int a_nCount,
const SOCHAR *
const * a_rgpszFileSpec);
590 SetArgvArrayType(POINTERS);
609 enum ARG_ARRAY_TYPE { OFFSETS, POINTERS };
612 void SetArgvArrayType(ARG_ARRAY_TYPE a_nNewType);
615 int AppendName(
const SOCHAR *a_pszFileName,
bool a_bIsDir);
618 bool GrowArgvArray(
int a_nNewLen);
621 bool GrowStringBuffer(
size_t a_uiMinSize);
624 static int fileSortCompare(
const void *a1,
const void *a2);
627 unsigned int m_uiFlags;
628 ARG_ARRAY_TYPE m_nArgArrayType;
630 int m_nReservedSlots;
634 size_t m_uiBufferSize;
635 size_t m_uiBufferLen;
643 template<
class SOCHAR>
645 unsigned int a_uiFlags,
654 Init(a_uiFlags, a_nReservedSlots);
657 template<
class SOCHAR>
660 if (m_rgpArgs) free(m_rgpArgs);
661 if (m_pBuffer) free(m_pBuffer);
664 template<
class SOCHAR>
667 unsigned int a_uiFlags,
671 m_nArgArrayType = POINTERS;
672 m_uiFlags = a_uiFlags;
673 m_nArgsLen = a_nReservedSlots;
674 m_nReservedSlots = a_nReservedSlots;
677 if (m_nReservedSlots > 0) {
678 if (!GrowArgvArray(m_nReservedSlots)) {
681 for (
int n = 0; n < m_nReservedSlots; ++n) {
689 template<
class SOCHAR>
692 const SOCHAR *a_pszFileSpec
706 a_pszFileSpec = szFileSpec;
710 m_szPathPrefix[0] = 0;
714 SG_FileType nType = this->GetFileTypeS(a_pszFileSpec);
717 return AppendName(a_pszFileSpec,
false);
728 const SOCHAR * pszFilename =
732 m_szPathPrefix[pszFilename - a_pszFileSpec + 1] = 0;
737 int rc = this->FindFirstFileS(a_pszFileSpec, m_uiFlags);
740 int ok = AppendName(a_pszFileSpec,
false);
747 int nError, nStartLen = m_nArgsLen;
750 nError = AppendName(this->GetFileNameS((SOCHAR)0), this->IsDirS((SOCHAR)0));
751 bSuccess = this->FindNextFileS((SOCHAR)0);
759 nStartLen = m_nReservedSlots;
761 SetArgvArrayType(POINTERS);
763 m_rgpArgs + nStartLen,
764 m_nArgsLen - nStartLen,
765 sizeof(m_rgpArgs[0]), fileSortCompare);
771 template<
class SOCHAR>
775 const SOCHAR *
const * a_rgpszFileSpec
779 for (
int n = 0; n < a_nCount; ++n) {
780 nResult = Add(a_rgpszFileSpec[n]);
788 template<
class SOCHAR>
791 const SOCHAR * a_pszFileName,
796 SetArgvArrayType(OFFSETS);
806 if (a_pszFileName[0] ==
'.') {
807 if (a_pszFileName[1] ==
'\0') {
810 if (a_pszFileName[1] ==
'.' && a_pszFileName[2] ==
'\0') {
817 if (!GrowArgvArray(m_nArgsLen + 1)) {
827 if (!GrowStringBuffer(m_uiBufferLen + uiLen)) {
832 m_rgpArgs[m_nArgsLen++] = (SOCHAR*)m_uiBufferLen;
834 m_uiBufferSize - m_uiBufferLen, m_szPathPrefix);
836 m_uiBufferSize - m_uiBufferLen - uiPrefixLen, a_pszFileName);
837 m_uiBufferLen += uiLen;
843 m_uiBufferSize - (m_uiBufferLen - 2), szDirSlash);
849 template<
class SOCHAR>
852 ARG_ARRAY_TYPE a_nNewType
855 if (m_nArgArrayType == a_nNewType)
return;
856 if (a_nNewType == POINTERS) {
858 for (
int n = 0; n < m_nArgsLen; ++n) {
859 m_rgpArgs[n] = (m_rgpArgs[n] == (SOCHAR*)-1) ?
860 NULL : m_pBuffer + (size_t) m_rgpArgs[n];
866 for (
int n = 0; n < m_nArgsLen; ++n) {
867 m_rgpArgs[n] = (m_rgpArgs[n] == NULL) ?
868 (SOCHAR*) -1 : (SOCHAR*) (m_rgpArgs[n] - m_pBuffer);
871 m_nArgArrayType = a_nNewType;
874 template<
class SOCHAR>
880 if (a_nNewLen >= m_nArgsSize) {
881 static const int SG_ARGV_INITIAL_SIZE = 32;
882 int nNewSize = (m_nArgsSize > 0) ?
883 m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE;
884 while (a_nNewLen >= nNewSize) {
887 void * pNewBuffer = realloc(m_rgpArgs, nNewSize *
sizeof(SOCHAR*));
888 if (!pNewBuffer)
return false;
889 m_nArgsSize = nNewSize;
890 m_rgpArgs = (SOCHAR**) pNewBuffer;
895 template<
class SOCHAR>
901 if (a_uiMinSize >= m_uiBufferSize) {
902 static const int SG_BUFFER_INITIAL_SIZE = 1024;
903 size_t uiNewSize = (m_uiBufferSize > 0) ?
904 m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE;
905 while (a_uiMinSize >= uiNewSize) {
908 void * pNewBuffer = realloc(m_pBuffer, uiNewSize *
sizeof(SOCHAR));
909 if (!pNewBuffer)
return false;
910 m_uiBufferSize = uiNewSize;
911 m_pBuffer = (SOCHAR*) pNewBuffer;
916 template<
class SOCHAR>
923 const SOCHAR * s1 = *(
const SOCHAR **)a1;
924 const SOCHAR * s2 = *(
const SOCHAR **)a2;
929 return s1 == s2 ? 0 : (s1 ? 1 : -1);
950 # define CSimpleGlob CSimpleGlobU
952 # define CSimpleGlob CSimpleGlobW
956 # define CSimpleGlob CSimpleGlobA
SG_Flags
The operation of SimpleGlob is fine-tuned via the use of a combination of the following flags.
#define sg_strcpy_s(a, n, b)
CSimpleGlobTempl< wchar_t > CSimpleGlobW
wchar_t version of CSimpleGlob
CSimpleGlobTempl< char > CSimpleGlobA
ASCII/MBCS version of CSimpleGlob.
SG_Error
Error return codes.
Implementation of the SimpleGlob class.
int Init(unsigned int a_uiFlags=0, int a_nReservedSlots=0)
Initialize (or re-initialize) the class in preparation for adding new filespecs.
~CSimpleGlobTempl()
Deallocate all memory buffers.
int FileCount() const
Return the number of files in the argv array.
int Add(const SOCHAR *a_pszFileSpec)
Add a new filespec to the glob.
SOCHAR * File(int n)
Return the a single file.
SOCHAR ** Files()
Return the full argv array.
CSimpleGlobTempl(unsigned int a_uiFlags=0, int a_nReservedSlots=0)
Initialize the class.
String manipulation functions.
static int strcasecmp(const char *s1, const char *s2)
static size_t strlen(const wchar_t *s)
static void strcpy_s(wchar_t *dst, size_t n, const wchar_t *src)
static const wchar_t * strrchr(const wchar_t *s, wchar_t c)
static const char * strchr(const char *s, char c)
static int strcmp(const char *s1, const char *s2)
static const wchar_t * strchr(const wchar_t *s, wchar_t c)
static int strcmp(const wchar_t *s1, const wchar_t *s2)
static const char * strrchr(const char *s, char c)
static void strcpy_s(char *dst, size_t n, const char *src)
static size_t strlen(const char *s)
Unix glob implementation.
SG_FileType GetFileTypeS(const char *a_pszPath) const
const char * GetFileNameS(char) const
int FindFirstFileS(const char *a_pszFileSpec, unsigned int a_uiFlags)