strigi/src/streams
fnmatch.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <ctype.h>
00038 #include "strigi_fnmatch.h"
00039
00040
00041
00042
00043
00044 #include <string.h>
00045
00046 #define EOS '\0'
00047
00048 static const char *rangematch(const char *, int, int);
00049
00050 int fnmatch(const char *pattern, const char *string, int flags)
00051 {
00052 const char *stringstart;
00053 char c, test;
00054
00055 for (stringstart = string;;) {
00056 switch (c = *pattern++) {
00057 case EOS:
00058 return (*string == EOS ? SUCCESS : FNM_NOMATCH);
00059 case '?':
00060 if (*string == EOS) {
00061 return (FNM_NOMATCH);
00062 }
00063 if (*string == '/' && (flags & FNM_PATHNAME)) {
00064 return (FNM_NOMATCH);
00065 }
00066 if (*string == '.' && (flags & FNM_PERIOD) &&
00067 (string == stringstart ||
00068 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
00069 return (FNM_NOMATCH);
00070 }
00071 ++string;
00072 break;
00073 case '*':
00074 c = *pattern;
00075
00076 while (c == '*') {
00077 c = *++pattern;
00078 }
00079
00080 if (*string == '.' && (flags & FNM_PERIOD) &&
00081 (string == stringstart ||
00082 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
00083 return (FNM_NOMATCH);
00084 }
00085
00086
00087 if (c == EOS) {
00088 if (flags & FNM_PATHNAME) {
00089 return (strchr(string, '/') == NULL ? SUCCESS : FNM_NOMATCH);
00090 }
00091 else {
00092 return (SUCCESS);
00093 }
00094 }
00095 else if (c == '/' && flags & FNM_PATHNAME) {
00096 if ((string = strchr(string, '/')) == NULL) {
00097 return (FNM_NOMATCH);
00098 }
00099 break;
00100 }
00101
00102
00103 while ((test = *string) != EOS) {
00104 if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
00105 return (SUCCESS);
00106 }
00107 if (test == '/' && flags & FNM_PATHNAME) {
00108 break;
00109 }
00110 ++string;
00111 }
00112 return (FNM_NOMATCH);
00113 case '[':
00114 if (*string == EOS) {
00115 return (FNM_NOMATCH);
00116 }
00117 if (*string == '/' && flags & FNM_PATHNAME) {
00118 return (FNM_NOMATCH);
00119 }
00120 if (*string == '.' && (flags & FNM_PERIOD) &&
00121 (string == stringstart ||
00122 ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
00123 return (FNM_NOMATCH);
00124 }
00125 if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
00126 return (FNM_NOMATCH);
00127 }
00128 ++string;
00129 break;
00130 case '\\':
00131 if (!(flags & FNM_NOESCAPE)) {
00132 if ((c = *pattern++) == EOS) {
00133 c = '\\';
00134 --pattern;
00135 }
00136 }
00137
00138 default:
00139 if (flags & FNM_CASE_BLIND) {
00140 if (tolower(c) != tolower(*string)) {
00141 return (FNM_NOMATCH);
00142 }
00143 }
00144 else if (c != *string) {
00145 return (FNM_NOMATCH);
00146 }
00147 string++;
00148 break;
00149 }
00150
00151 }
00152 }
00153
00154 static const char *rangematch(const char *pattern, int test, int flags)
00155 {
00156 int negate, ok;
00157 char c, c2;
00158
00159
00160
00161
00162
00163
00164
00165
00166 if ((negate = (*pattern == '!' || *pattern == '^'))) {
00167 ++pattern;
00168 }
00169
00170 for (ok = 0; (c = *pattern++) != ']';) {
00171 if (c == '\\' && !(flags & FNM_NOESCAPE)) {
00172 c = *pattern++;
00173 }
00174 if (c == EOS) {
00175 return (NULL);
00176 }
00177 if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
00178 pattern += 2;
00179 if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
00180 c2 = *pattern++;
00181 }
00182 if (c2 == EOS) {
00183 return (NULL);
00184 }
00185 if ((c <= test && test <= c2)
00186 || ((flags & FNM_CASE_BLIND)
00187 && ((tolower(c) <= tolower(test))
00188 && (tolower(test) <= tolower(c2))))) {
00189 ok = 1;
00190 }
00191 }
00192 else if ((c == test)
00193 || ((flags & FNM_CASE_BLIND)
00194 && (tolower(c) == tolower(test)))) {
00195 ok = 1;
00196 }
00197 }
00198 return (ok == negate ? NULL : pattern);
00199 }
00200
00201
00202
00203
00204 int fnmatch_test(const char *pattern)
00205 {
00206 int nesting;
00207
00208 nesting = 0;
00209 while (*pattern) {
00210 switch (*pattern) {
00211 case '?':
00212 case '*':
00213 return 1;
00214
00215 case '\\':
00216 if (*pattern++ == '\0') {
00217 return 0;
00218 }
00219 break;
00220
00221 case '[':
00222 ++nesting;
00223 break;
00224
00225 case ']':
00226 if (nesting) {
00227 return 1;
00228 }
00229 break;
00230 }
00231 ++pattern;
00232 }
00233 return 0;
00234 }
00235
00236
00237 int is_fnmatch(const char *pattern)
00238 {
00239 return fnmatch_test(pattern);
00240 }