17 #ifndef THRILL_VFS_SIMPLE_GLOB_HEADER 18 #define THRILL_VFS_SIMPLE_GLOB_HEADER 26 # if !defined(_WIN32) && defined(USTRING_H) 27 # define SG_HAVE_ICU 1 29 # define SG_HAVE_ICU 0 39 # include <mbstring.h> 41 # define sg_strchr ::_mbschr 42 # define sg_strrchr ::_mbsrchr 43 # define sg_strlen ::_mbslen 44 # if __STDC_WANT_SECURE_LIB__ 45 # define sg_strcpy_s(a, n, b) ::_mbscpy_s(a, n, b) 47 # define sg_strcpy_s(a, n, b) ::_mbscpy(a, b) 49 # define sg_strcmp ::_mbscmp 50 # define sg_strcasecmp ::_mbsicmp 51 # define SOCHAR_T unsigned char 55 # include <sys/stat.h> 56 # include <sys/types.h> 57 # define MAX_PATH PATH_MAX 58 # define sg_strchr ::strchr 59 # define sg_strrchr ::strrchr 60 # define sg_strlen ::strlen 61 # define sg_strcpy_s(a, n, b) ::strcpy(a, b) // NOLINT 62 # define sg_strcmp ::strcmp 63 # define sg_strcasecmp ::strcasecmp 64 # define SOCHAR_T char 76 # define SG_ASSERT(b) _ASSERTE(b) 79 # define SG_ASSERT(b) assert(b) 87 namespace glob_local {
238 static const char *
strchr(
const char* s,
char c) {
239 return reinterpret_cast<const char*
>(
240 sg_strchr(reinterpret_cast<const SOCHAR_T*>(s), c));
242 static const wchar_t *
strchr(
const wchar_t* s,
wchar_t c) {
243 return ::wcschr(s, c);
246 static const UChar *
strchr(
const UChar* s, UChar c) {
247 return ::u_strchr(s, c);
251 static const char *
strrchr(
const char* s,
char c) {
252 return reinterpret_cast<const char*
>(
253 sg_strrchr(reinterpret_cast<const SOCHAR_T*>(s), c));
255 static const wchar_t *
strrchr(
const wchar_t* s,
wchar_t c) {
256 return ::wcsrchr(s, c);
259 static const UChar *
strrchr(
const UChar* s, UChar c) {
260 return ::u_strrchr(s, c);
265 static size_t strlen(
const char* s) { return ::strlen(s); }
266 static size_t strlen(
const wchar_t* s) { return ::wcslen(s); }
268 static size_t strlen(
const UChar* s) { return ::u_strlen(s); }
271 static void strcpy_s(
char* dst,
size_t n,
const char* src) {
274 reinterpret_cast<const SOCHAR_T*>(src));
276 static void strcpy_s(
wchar_t* dst,
size_t n,
const wchar_t* src) {
277 # if __STDC_WANT_SECURE_LIB__ 278 ::wcscpy_s(dst, n, src);
285 static void strcpy_s(UChar* dst,
size_t n,
const UChar* src) {
286 ::u_strncpy(dst, src, n);
290 static int strcmp(
const char* s1,
const char* s2) {
293 static int strcmp(
const wchar_t* s1,
const wchar_t* s2) {
294 return ::wcscmp(s1, s2);
297 static int strcmp(
const UChar* s1,
const UChar* s2) {
298 return ::u_strcmp(s1, s2);
306 static int strcasecmp(
const wchar_t* s1,
const wchar_t* s2) {
307 return ::_wcsicmp(s1, s2);
311 static int strcasecmp(
const UChar* s1,
const UChar* s2) {
312 return u_strcasecmp(s1, s2, 0);
325 #ifndef INVALID_FILE_ATTRIBUTES 326 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 329 #define SG_PATH_CHAR '\\' 332 template <
typename SOCHAR>
338 int FindFirstFileS(
const char* a_pszFileSpec,
unsigned int) {
339 m_hFind = FindFirstFileA(a_pszFileSpec, &m_oFindDataA);
340 if (m_hFind != INVALID_HANDLE_VALUE) {
343 DWORD dwErr = GetLastError();
344 if (dwErr == ERROR_FILE_NOT_FOUND) {
349 int FindFirstFileS(
const wchar_t* a_pszFileSpec,
unsigned int) {
350 m_hFind = FindFirstFileW(a_pszFileSpec, &m_oFindDataW);
351 if (m_hFind != INVALID_HANDLE_VALUE) {
354 DWORD dwErr = GetLastError();
355 if (dwErr == ERROR_FILE_NOT_FOUND) {
361 bool FindNextFileS(
char) {
362 return FindNextFileA(m_hFind, &m_oFindDataA) != FALSE;
364 bool FindNextFileS(
wchar_t) {
365 return FindNextFileW(m_hFind, &m_oFindDataW) != FALSE;
372 const char * GetFileNameS(
char)
const {
373 return m_oFindDataA.cFileName;
375 const wchar_t * GetFileNameS(
wchar_t)
const {
376 return m_oFindDataW.cFileName;
379 bool IsDirS(
char)
const {
380 return this->GetFileTypeS(m_oFindDataA.dwFileAttributes) ==
SG_FILETYPE_DIR;
382 bool IsDirS(
wchar_t)
const {
383 return this->GetFileTypeS(m_oFindDataW.dwFileAttributes) ==
SG_FILETYPE_DIR;
387 return this->GetFileTypeS(GetFileAttributesA(a_pszPath));
389 SG_FileType GetFileTypeS(
const wchar_t* a_pszPath) {
390 return this->GetFileTypeS(GetFileAttributesW(a_pszPath));
392 SG_FileType GetFileTypeS(DWORD a_dwAttribs)
const {
393 if (a_dwAttribs == INVALID_FILE_ATTRIBUTES) {
396 if (a_dwAttribs & FILE_ATTRIBUTE_DIRECTORY) {
404 WIN32_FIND_DATAA m_oFindDataA;
405 WIN32_FIND_DATAW m_oFindDataW;
410 #define SG_PATH_CHAR '/' 413 template <
typename SOCHAR>
418 memset(&glob_, 0,
sizeof(glob_));
419 ui_curr_ = (size_t)-1;
428 size_t len =
strlen(glob_.gl_pathv[ui_curr_]);
429 if (glob_.gl_pathv[ui_curr_][len - 1] ==
'/') {
431 glob_.gl_pathv[ui_curr_][len - 1] = 0;
436 int nflags = GLOB_MARK | GLOB_NOSORT;
439 int rc = glob(a_pszFileSpec, nflags,
nullptr, &glob_);
449 int FindFirstFileS(
const UChar* a_pszFileSpec,
unsigned int a_uiFlags) {
450 char buf[PATH_MAX] = { 0 };
451 UErrorCode status = U_ZERO_ERROR;
452 u_strToUTF8(buf,
sizeof(buf),
nullptr, a_pszFileSpec, -1, &status);
454 return this->FindFirstFileS(buf, a_uiFlags);
460 if (++ui_curr_ >= glob_.gl_pathc) {
468 bool FindNextFileS(UChar) {
469 return this->FindNextFileS(static_cast<char>(0));
475 memset(&glob_, 0,
sizeof(glob_));
476 ui_curr_ = (size_t)-1;
481 return glob_.gl_pathv[ui_curr_];
485 const UChar * GetFileNameS(UChar)
const {
486 const char* pszFile = this->GetFileNameS(static_cast<char>(0));
487 if (!pszFile)
return nullptr;
488 UErrorCode status = U_ZERO_ERROR;
489 memset(m_szBuf, 0,
sizeof(m_szBuf));
490 u_strFromUTF8(m_szBuf, PATH_MAX,
nullptr, pszFile, -1, &status);
491 if (U_FAILURE(status))
return nullptr;
502 bool IsDirS(UChar)
const {
503 return this->IsDirS(static_cast<char>(0));
509 if (0 != stat(a_pszPath, &sb)) {
512 if (S_ISDIR(sb.st_mode)) {
515 if (S_ISREG(sb.st_mode)) {
522 SG_FileType GetFileTypeS(
const UChar* a_pszPath)
const {
523 char buf[PATH_MAX] = { 0 };
524 UErrorCode status = U_ZERO_ERROR;
525 u_strToUTF8(buf,
sizeof(buf),
nullptr, a_pszPath, -1, &status);
527 return this->GetFileTypeS(buf);
536 mutable UChar m_szBuf[PATH_MAX];
549 template <
typename SOCHAR>
561 explicit CSimpleGlobTempl(
unsigned int a_uiFlags = 0,
int a_nReservedSlots = 0);
578 int Init(
unsigned int a_uiFlags = 0,
int a_nReservedSlots = 0);
593 int Add(
const SOCHAR* a_pszFileSpec);
609 int Add(
int a_nCount,
const SOCHAR*
const* a_rgpszFileSpec);
617 SetArgvArrayType(POINTERS);
642 int AppendName(
const SOCHAR* a_pszFileName,
bool a_bIsDir);
645 bool GrowArgvArray(
int a_nNewLen);
648 bool GrowStringBuffer(
size_t a_uiMinSize);
651 static int fileSortCompare(
const void* a1,
const void* a2);
670 template <
typename SOCHAR>
672 unsigned int a_uiFlags,
680 Init(a_uiFlags, a_nReservedSlots);
683 template <
typename SOCHAR>
685 if (m_rgpArgs)
free(m_rgpArgs);
686 if (m_pBuffer)
free(m_pBuffer);
689 template <
typename SOCHAR>
692 unsigned int a_uiFlags,
695 m_nArgArrayType = POINTERS;
696 m_uiFlags = a_uiFlags;
697 m_nArgsLen = a_nReservedSlots;
698 m_nReservedSlots = a_nReservedSlots;
701 if (m_nReservedSlots > 0) {
702 if (!GrowArgvArray(m_nReservedSlots)) {
705 for (
int n = 0; n < m_nReservedSlots; ++n) {
706 m_rgpArgs[n] =
nullptr;
713 template <
typename SOCHAR>
716 const SOCHAR* a_pszFileSpec
729 a_pszFileSpec = szFileSpec;
733 m_szPathPrefix[0] = 0;
737 SG_FileType nType = this->GetFileTypeS(a_pszFileSpec);
740 return AppendName(a_pszFileSpec,
false);
751 const SOCHAR* pszFilename =
755 m_szPathPrefix[pszFilename - a_pszFileSpec + 1] = 0;
760 int rc = this->FindFirstFileS(a_pszFileSpec, m_uiFlags);
763 int ok = AppendName(a_pszFileSpec,
false);
770 int nError, nStartLen = m_nArgsLen;
773 nError = AppendName(this->GetFileNameS((SOCHAR)0), this->IsDirS((SOCHAR)0));
774 bSuccess = this->FindNextFileS((SOCHAR)0);
782 nStartLen = m_nReservedSlots;
784 SetArgvArrayType(POINTERS);
786 m_rgpArgs + nStartLen,
787 m_nArgsLen - nStartLen,
788 sizeof(m_rgpArgs[0]), fileSortCompare);
794 template <
typename SOCHAR>
798 const SOCHAR*
const* a_rgpszFileSpec
801 for (
int n = 0; n < a_nCount; ++n) {
802 nResult = Add(a_rgpszFileSpec[n]);
810 template <
typename SOCHAR>
813 const SOCHAR* a_pszFileName,
817 SetArgvArrayType(OFFSETS);
827 if (a_pszFileName[0] ==
'.') {
828 if (a_pszFileName[1] ==
'\0') {
831 if (a_pszFileName[1] ==
'.' && a_pszFileName[2] ==
'\0') {
838 if (!GrowArgvArray(m_nArgsLen + 1)) {
845 if (a_bIsDir && (m_uiFlags &
SG_GLOB_MARK) == SG_GLOB_MARK) {
848 if (!GrowStringBuffer(m_uiBufferLen + uiLen)) {
853 m_rgpArgs[m_nArgsLen++] =
reinterpret_cast<SOCHAR*
>(m_uiBufferLen);
855 m_uiBufferSize - m_uiBufferLen, m_szPathPrefix);
857 m_uiBufferSize - m_uiBufferLen - uiPrefixLen, a_pszFileName);
858 m_uiBufferLen += uiLen;
861 if (a_bIsDir && (m_uiFlags & SG_GLOB_MARK) == SG_GLOB_MARK) {
864 m_uiBufferSize - (m_uiBufferLen - 2), szDirSlash);
870 template <
typename SOCHAR>
875 if (m_nArgArrayType == a_nNewType)
return;
876 if (a_nNewType == POINTERS) {
878 for (
int n = 0; n < m_nArgsLen; ++n) {
879 m_rgpArgs[n] = (m_rgpArgs[n] ==
reinterpret_cast<SOCHAR*
>(-1)) ?
880 nullptr : m_pBuffer + (size_t)m_rgpArgs[n];
886 for (
int n = 0; n < m_nArgsLen; ++n) {
887 m_rgpArgs[n] = (m_rgpArgs[n] ==
nullptr) ?
888 reinterpret_cast<SOCHAR*>(-1) :
889 reinterpret_cast<SOCHAR*
>(m_rgpArgs[n] - m_pBuffer);
892 m_nArgArrayType = a_nNewType;
895 template <
typename SOCHAR>
900 if (a_nNewLen >= m_nArgsSize) {
901 static const int SG_ARGV_INITIAL_SIZE = 32;
902 int nNewSize = (m_nArgsSize > 0) ?
903 m_nArgsSize * 2 : SG_ARGV_INITIAL_SIZE;
904 while (a_nNewLen >= nNewSize) {
907 void* pNewBuffer =
realloc(m_rgpArgs, nNewSize *
sizeof(SOCHAR*));
908 if (!pNewBuffer)
return false;
909 m_nArgsSize = nNewSize;
910 m_rgpArgs =
reinterpret_cast<SOCHAR**
>(pNewBuffer);
915 template <
typename SOCHAR>
920 if (a_uiMinSize >= m_uiBufferSize) {
921 static const int SG_BUFFER_INITIAL_SIZE = 1024;
922 size_t uiNewSize = (m_uiBufferSize > 0) ?
923 m_uiBufferSize * 2 : SG_BUFFER_INITIAL_SIZE;
924 while (a_uiMinSize >= uiNewSize) {
927 void* pNewBuffer =
realloc(m_pBuffer, uiNewSize *
sizeof(SOCHAR));
928 if (!pNewBuffer)
return false;
929 m_uiBufferSize = uiNewSize;
930 m_pBuffer =
reinterpret_cast<SOCHAR*
>(pNewBuffer);
935 template <
typename SOCHAR>
941 const SOCHAR* s1 = *(
const SOCHAR**)a1;
942 const SOCHAR* s2 = *(
const SOCHAR**)a2;
947 return s1 == s2 ? 0 : (s1 ? 1 : -1);
968 # define CSimpleGlob CSimpleGlobU 970 # define CSimpleGlob CSimpleGlobW 974 # define CSimpleGlob CSimpleGlobA 981 #endif // !THRILL_VFS_SIMPLE_GLOB_HEADER
int m_nArgsSize
allocated size of array
Unix glob implementation.
int m_nArgsLen
used length
const char * GetFileNameS(char) const
static const char * strrchr(const char *s, char c)
static void strcpy_s(char *dst, size_t n, const char *src)
static int strcasecmp(const char *s1, const char *s2)
~CSimpleGlobTempl()
Deallocate all memory buffers.
static size_t strlen(const char *s)
ARG_ARRAY_TYPE m_nArgArrayType
argv is indexes or pointers
int FindFirstFileS(const char *a_pszFileSpec, unsigned int a_uiFlags)
SOCHAR * m_pBuffer
argv string buffer
size_t m_uiBufferLen
used length of buffer
bool GrowArgvArray(int a_nNewLen)
Grow the argv array to the required size.
int AppendName(const SOCHAR *a_pszFileName, bool a_bIsDir)
Add a filename to the array if it passes all requirements.
SG_Error
Error return codes.
int Add(const SOCHAR *a_pszFileSpec)
Add a new filespec to the glob.
SOCHAR ** Files()
Return the full argv array.
Implementation of the SimpleGlob class.
static int strcmp(const wchar_t *s1, const wchar_t *s2)
size_t m_uiBufferSize
allocated size of buffer
String manipulation functions.
int m_nReservedSlots
client slots in argv array
static const wchar_t * strrchr(const wchar_t *s, wchar_t c)
void SetArgvArrayType(ARG_ARRAY_TYPE a_nNewType)
Change the type of data stored in the argv array.
int FileCount() const
Return the number of files in the argv array.
static int strcmp(const char *s1, const char *s2)
static size_t strlen(const wchar_t *s)
SOCHAR * File(int n)
Return the a single file.
SG_Flags
The operation of SimpleGlob is fine-tuned via the use of a combination of the following flags...
static void strcpy_s(wchar_t *dst, size_t n, const wchar_t *src)
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.
int Init(unsigned int a_uiFlags=0, int a_nReservedSlots=0)
Initialize (or re-initialize) the class in preparation for adding new filespecs.
static const wchar_t * strchr(const wchar_t *s, wchar_t c)
SG_FileType GetFileTypeS(const char *a_pszPath) const
#define sg_strcpy_s(a, n, b)
void free(void *ptr) NOEXCEPT
exported free symbol that overrides loading from libc
CSimpleGlobTempl(unsigned int a_uiFlags=0, int a_nReservedSlots=0)
Initialize the class.
bool GrowStringBuffer(size_t a_uiMinSize)
Grow the string buffer to the required size.
void * realloc(void *ptr, size_t size) NOEXCEPT
exported realloc() symbol that overrides loading from libc
static const char * strchr(const char *s, char c)
static int fileSortCompare(const void *a1, const void *a2)
Compare two (possible nullptr) strings.