git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33948 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
368 lines
8.4 KiB
C++
368 lines
8.4 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: glob.inc
|
|
// Purpose: File and other globbing (included by utils.cpp)
|
|
// Author: Karsten Ballueder
|
|
// Modified by:
|
|
// Created: 20/5/1998
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Karsten Ballueder
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// This file includes:
|
|
// wxIsWild(const char *pattern)
|
|
// wxMatchWild(const char *pattern, const char *str, bool dot_special)
|
|
//
|
|
|
|
//---------------------------------------------------------------------------------
|
|
#ifndef UNIX_GLOB
|
|
# ifdef wx_x
|
|
# define UNIX_GLOB 1
|
|
# else
|
|
# define UNIX_GLOB 0
|
|
# endif
|
|
#endif
|
|
|
|
#if UNIX_GLOB
|
|
# ifdef wx_msw
|
|
# error "Can't use Unix file globbing under Windows!"
|
|
# endif
|
|
#endif
|
|
|
|
/*************************************************************************
|
|
*
|
|
* wxIsWild checks whether the pattern contains wildcards, and
|
|
* returns TRUE if it does, and FALSE if it does not (or if the
|
|
* pattern is NULL -- i.e. no string).
|
|
*
|
|
* The argument is:
|
|
*
|
|
* 1) pattern - a character string
|
|
*/
|
|
bool
|
|
wxIsWild (const char *pattern)
|
|
{
|
|
while (*pattern)
|
|
{
|
|
switch (*pattern++)
|
|
{
|
|
case '?':
|
|
case '*':
|
|
#if UNIX_GLOB
|
|
case '[':
|
|
case '{': /* } */
|
|
#endif
|
|
return TRUE;
|
|
#if UNIX_GLOB
|
|
case '\\':
|
|
if (!*pattern++)
|
|
return FALSE;
|
|
#endif
|
|
} /* switch() */
|
|
} /* while() */
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
#if UNIX_GLOB
|
|
|
|
// Unix Glob()
|
|
//
|
|
// Pattern Function
|
|
// -----------------------------------------------------
|
|
// '*' = match 0 or more occurances of anything
|
|
// "[abc]" = match anyof "abc" (ranges supported)
|
|
// "{xx,yy,zz}" = match anyof "xx", "yy", or "zz"
|
|
// '?' = match any character
|
|
//
|
|
// '\' is used to "escape" special characters
|
|
// Recursive
|
|
|
|
bool
|
|
wxMatchWild (const char *pattern, const char *str, bool dot_special)
|
|
{
|
|
char c;
|
|
const char *cp;
|
|
bool done = FALSE, ret_code, ok;
|
|
// Below is for vi fans
|
|
const char OB = '{', CB = '}';
|
|
|
|
#if 0
|
|
if (strcmp(pattern, "*.*") == 0)
|
|
pattern = "*"; // Hack for MS-DOS compat.
|
|
#endif
|
|
|
|
// dot_special means '.' only matches '.'
|
|
if (dot_special && *str == '.' && *pattern != *str)
|
|
return FALSE;
|
|
|
|
while ((*pattern != '\0') && (!done) && (((*str == '\0') &&
|
|
((*pattern == OB) || (*pattern == '*'))) || (*str != '\0')))
|
|
{
|
|
switch (*pattern)
|
|
{
|
|
case '\\':
|
|
pattern++;
|
|
if (*pattern != '\0')
|
|
pattern++;
|
|
break;
|
|
case '*':
|
|
pattern++;
|
|
ret_code = FALSE;
|
|
while ((*str != '\0') && (!(ret_code = wxMatchWild (pattern, str++, FALSE))));
|
|
if (ret_code)
|
|
{
|
|
while (*str != '\0')
|
|
str++;
|
|
while (*pattern != '\0')
|
|
pattern++;
|
|
}
|
|
break;
|
|
case '[':
|
|
pattern++;
|
|
repeat:
|
|
if ((*pattern == '\0') || (*pattern == ']'))
|
|
{
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
if (*pattern == '\\')
|
|
{
|
|
pattern++;
|
|
if (*pattern == '\0')
|
|
{
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (*(pattern + 1) == '-')
|
|
{
|
|
c = *pattern;
|
|
pattern += 2;
|
|
if (*pattern == ']')
|
|
{
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
if (*pattern == '\\')
|
|
{
|
|
pattern++;
|
|
if (*pattern == '\0')
|
|
{
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if ((*str < c) || (*str > *pattern))
|
|
{
|
|
pattern++;
|
|
goto repeat;
|
|
}
|
|
}
|
|
else if (*pattern != *str)
|
|
{
|
|
pattern++;
|
|
goto repeat;
|
|
}
|
|
pattern++;
|
|
while ((*pattern != ']') && (*pattern != '\0'))
|
|
{
|
|
if ((*pattern == '\\') && (*(pattern + 1) != '\0'))
|
|
pattern++;
|
|
pattern++;
|
|
} // while()
|
|
if (*pattern != '\0')
|
|
{
|
|
pattern++, str++;
|
|
}
|
|
break;
|
|
case '?':
|
|
pattern++;
|
|
str++;
|
|
break;
|
|
case OB:
|
|
pattern++;
|
|
while ((*pattern != CB) && (*pattern != '\0'))
|
|
{
|
|
cp = str;
|
|
ok = TRUE;
|
|
while (ok && (*cp != '\0') && (*pattern != '\0') &&
|
|
(*pattern != ',') && (*pattern != CB))
|
|
{
|
|
if (*pattern == '\\')
|
|
pattern++;
|
|
ok = (*pattern++ == *cp++);
|
|
} // while()
|
|
if (*pattern == '\0')
|
|
{
|
|
ok = FALSE;
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
else if (ok)
|
|
{
|
|
str = cp;
|
|
while ((*pattern != CB) && (*pattern != '\0'))
|
|
{
|
|
if (*++pattern == '\\')
|
|
{
|
|
if (*++pattern == CB)
|
|
pattern++;
|
|
}
|
|
} // while()
|
|
}
|
|
else
|
|
{
|
|
while (*pattern != CB && *pattern != ',' && *pattern != '\0')
|
|
{
|
|
if (*++pattern == '\\')
|
|
{
|
|
if (*++pattern == CB || *pattern == ',')
|
|
pattern++;
|
|
}
|
|
} // while()
|
|
}
|
|
if (*pattern != '\0')
|
|
pattern++;
|
|
} // while()
|
|
break;
|
|
default:
|
|
if (*str == *pattern)
|
|
{
|
|
str++, pattern++;
|
|
}
|
|
else
|
|
{
|
|
done = TRUE;
|
|
}
|
|
} // switch()
|
|
} // while()
|
|
while (*pattern == '*')
|
|
pattern++;
|
|
return ((*str == '\0') && (*pattern == '\0'));
|
|
}
|
|
|
|
#else /* MS-DOS/Windows glob() */
|
|
/*************************************************************************
|
|
*
|
|
* wxMatchWild matches the given pattern string against
|
|
* a text string, and returns TRUE if it matches, FALSE otherwise.
|
|
*
|
|
* A match means that the entire text string is used up in the matching.
|
|
* The pattern can contain the following wildcards.
|
|
*
|
|
* * -- matches any sequence of characters
|
|
* ? -- matches one character
|
|
*
|
|
* If one or other or both of the string arguments to wxMatchWild function is
|
|
* NULL (i.e. there isn't a string), then the function returns FALSE.
|
|
*
|
|
*/
|
|
static bool wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j);
|
|
|
|
// @@@@ dotSpecial is ignored by MS-DOS
|
|
bool
|
|
wxMatchWild (const char *pattern, const char *text, bool /* dotSpecial */ )
|
|
{
|
|
if (pattern == NULL || text == NULL || *pattern == '\0' || *text == '\0')
|
|
return FALSE;
|
|
return wxPatternMatch (pattern, text, 0, 0);
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
* wxPatternMatch does the work for wxMatchWild. wxPatternMatch matches
|
|
* the given pattern string against a text string, and returns TRUE if
|
|
* it matches, FALSE otherwise. It is assumed that the string arguments
|
|
* to wxPatternMatch exist.
|
|
*
|
|
* A match means that the entire text string is used up in the matching.
|
|
* The pattern can contain the following wildcards.
|
|
*
|
|
* * -- matches any sequence of characters
|
|
* ? -- matches one character
|
|
*
|
|
* wxPatternMatch works by going down the pattern trying to match the
|
|
* the same index character in the pattern and string arrays, and stops
|
|
* when the end of the pattern or text string is reached. However, if a
|
|
* '*' wildcard is met, the algorithm checks to see whether the remaining
|
|
* pattern (after the wildcard) matches the rest of the text (i.e. the
|
|
* wxPatternMatch function is called recursively).
|
|
*/
|
|
// Recursive
|
|
static bool
|
|
wxPatternMatch (const char *pattern, const char *text, size_t i, size_t j)
|
|
{
|
|
size_t pattern_length = strlen (pattern);
|
|
size_t text_length = strlen (text);
|
|
bool match = FALSE;
|
|
|
|
#ifdef wx_msw
|
|
// MS-DOS file system is case INDEPENDENT
|
|
# define EQU(x,y) (wxToLower(x) == wxToLower(y))
|
|
#else
|
|
# define EQU(x,y) ((x) == (y))
|
|
#endif
|
|
|
|
while (j < pattern_length && i < text_length)
|
|
{
|
|
if (EQU(text[i], pattern[j]) || pattern[j] == '?')
|
|
{
|
|
match = TRUE;
|
|
i++, j++;
|
|
}
|
|
else if (pattern[j] == '*')
|
|
{
|
|
// If pattern ends in '*'
|
|
if (++j == pattern_length)
|
|
{
|
|
match = TRUE;
|
|
i = text_length;
|
|
}
|
|
else
|
|
{
|
|
match = FALSE;
|
|
// after wildcard check to see whether rest of pattern matches
|
|
// up with rest of text
|
|
while (i < text_length && match != TRUE)
|
|
{
|
|
match = wxPatternMatch (pattern, text, i, j);
|
|
i++;
|
|
}
|
|
// text index is decremented so that it points to where
|
|
// the text string starts to match the rest of the pattern
|
|
i--;
|
|
}
|
|
}
|
|
else if (! EQU(text[i], pattern[j]))
|
|
{
|
|
j = pattern_length;
|
|
match = FALSE;
|
|
}
|
|
}
|
|
if (j == pattern_length && i == text_length && match == TRUE)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
// special case where pattern and text are the same except that pattern
|
|
// also only has '*' wildcards on the end
|
|
if (i == text_length && pattern[j] == '*' && match == TRUE)
|
|
{
|
|
for (; j < pattern_length; j++)
|
|
{
|
|
if (pattern[j] != '*')
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#endif /* UNIX_GLOB */
|
|
//-----------------------------------------------------------------------------
|