curl-library
[PATCH] New function Curl_fnmatch() added
From: Pavel Raiskup <pavel_at_raiskup.cz>
Date: Mon, 26 Apr 2010 11:33:34 +0200
Date: Mon, 26 Apr 2010 11:33:34 +0200
--- lib/Makefile.inc | 4 +- lib/curl_fnmatch.c | 408 +++++++++++++++++++++++++++++++++++++= +++++++ lib/curl_fnmatch.h | 44 +++++ tests/data/Makefile.am | 3 +- tests/data/test573 | 36 ++++ tests/libtest/Makefile.inc | 3 +- tests/libtest/lib573.c | 211 +++++++++++++++++++++++ 7 files changed, 705 insertions(+), 4 deletions(-) create mode 100644 lib/curl_fnmatch.c create mode 100644 lib/curl_fnmatch.h create mode 100644 tests/data/test573 create mode 100644 tests/libtest/lib573.c diff --git a/lib/Makefile.inc b/lib/Makefile.inc index f90e4dc..230d780 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -12,7 +12,7 @@ CSOURCES =3D file.c timeval.c base64.c hostip.c progre= ss.c formdata.c \ strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c = \ socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \ curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c = \ - warnless.c hmac.c + warnless.c hmac.c curl_fnmatch.c = HHEADERS =3D arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \ progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \ @@ -25,4 +25,4 @@ HHEADERS =3D arpa_telnet.h netrc.h file.h timeval.h qs= sl.h hostip.h \ tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h = \ curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h= \ curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h = \ - warnless.h curl_hmac.h + warnless.h curl_hmac.h curl_fnmatch.h diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c new file mode 100644 index 0000000..b0650ba --- /dev/null +++ b/lib/curl_fnmatch.c @@ -0,0 +1,408 @@ +/**********************************************************************= ***** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel_at_haxx.se>, et al.= + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or = sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY O= F ANY + * KIND, either express or implied. + * + **********************************************************************= *****/ + +#include "curl_fnmatch.h" +#include "setup.h" + +#define CURLFNM_CHARSET_LEN (sizeof(char) * 256) +#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15) + +#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN + +#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1) +#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2) +#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3) +#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4) +#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5) +#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6) +#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7) +#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8) +#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9) +#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10) + +typedef enum { + CURLFNM_LOOP_DEFAULT =3D 0, + CURLFNM_LOOP_BACKSLASH +} loop_state; + +typedef enum { + CURLFNM_SCHS_DEFAULT =3D 0, + CURLFNM_SCHS_MAYRANGE, + CURLFNM_SCHS_MAYRANGE2, + CURLFNM_SCHS_RIGHTBR, + CURLFNM_SCHS_RIGHTBRLEFTBR +} setcharset_state; + +/* set charset to contain character */ +#define ADDCHAR(x) charset[x] =3D 1 +/* set charset to not contain character */ +#define REMCHAR(x) charset[x] =3D 0 + +typedef enum { + CURLFNM_PKW_INIT =3D 0, + CURLFNM_PKW_DDOT +} parsekey_state; + +#define SETCHARSET_OK 1 +#define SETCHARSET_FAIL 0 + +static int parsekeyword(unsigned char **pattern, unsigned char *charset= ) +{ + parsekey_state state =3D CURLFNM_PKW_INIT; +#define KEYLEN 10 + char keyword[KEYLEN] =3D { 0 }; + int found =3D FALSE; + int i; + register unsigned char *p =3D *pattern; + for(i =3D 0; !found; i++) { + char c =3D *p++; + if(i >=3D KEYLEN) + return SETCHARSET_FAIL; + switch(state) { + case CURLFNM_PKW_INIT: + if(ISALPHA(c) && ISLOWER(c)) + keyword[i] =3D c; + else if(c =3D=3D ':') + state =3D CURLFNM_PKW_DDOT; + else + return 0; + break; + case CURLFNM_PKW_DDOT: + if(c =3D=3D ']') + found =3D TRUE; + else + return SETCHARSET_FAIL; + } + } +#undef KEYLEN + + *pattern =3D p; /* move caller's pattern pointer */ + if(strcmp(keyword, "digit") =3D=3D 0) + charset[CURLFNM_DIGIT] =3D 1; + else if(strcmp(keyword, "alnum") =3D=3D 0) + charset[CURLFNM_ALNUM] =3D 1; + else if(strcmp(keyword, "alpha") =3D=3D 0) + charset[CURLFNM_ALPHA] =3D 1; + else if(strcmp(keyword, "xdigit") =3D=3D 0) + charset[CURLFNM_XDIGIT] =3D 1; + else if(strcmp(keyword, "print") =3D=3D 0) + charset[CURLFNM_PRINT] =3D 1; + else if(strcmp(keyword, "graph") =3D=3D 0) + charset[CURLFNM_GRAPH] =3D 1; + else if(strcmp(keyword, "space") =3D=3D 0) + charset[CURLFNM_SPACE] =3D 1; + else if(strcmp(keyword, "blank") =3D=3D 0) + charset[CURLFNM_BLANK] =3D 1; + else if(strcmp(keyword, "upper") =3D=3D 0) + charset[CURLFNM_UPPER] =3D 1; + else if(strcmp(keyword, "lower") =3D=3D 0) + charset[CURLFNM_LOWER] =3D 1; + else + return SETCHARSET_FAIL; + return SETCHARSET_OK; +} + +/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern point= er) */ +static int setcharset(unsigned char **p, unsigned char *charset) +{ + setcharset_state state =3D CURLFNM_SCHS_DEFAULT; + unsigned char rangestart =3D 0; + unsigned char lastchar =3D 0; + bool something_found =3D FALSE; + register unsigned char c; + for(;;) { + c =3D **p; + switch(state){ + case CURLFNM_SCHS_DEFAULT: + if(ISALNUM(c)) { /* ASCII value */ + rangestart =3D c; + ADDCHAR(c); + (*p)++; + state =3D CURLFNM_SCHS_MAYRANGE; + something_found =3D TRUE; + } + else if(c =3D=3D ']') { + if(something_found) + return SETCHARSET_OK; + else + something_found =3D TRUE; + state =3D CURLFNM_SCHS_RIGHTBR; + ADDCHAR(c); + (*p)++; + } + else if(c =3D=3D '[') { + char c2 =3D *((*p)+1); + if(c2 =3D=3D ':') { /* there has to be a keyword */ + (*p) +=3D 2; + if(parsekeyword(p, charset)) { + state =3D CURLFNM_SCHS_DEFAULT; + } + else + return SETCHARSET_FAIL; + } + else { + ADDCHAR(c); + (*p)++; + } + something_found =3D TRUE; + } + else if(c =3D=3D '?' || c =3D=3D '*') { + something_found =3D TRUE; + ADDCHAR(c); + (*p)++; + } + else if(c =3D=3D '^' || c =3D=3D '!') { + if(!something_found) { + if(charset[CURLFNM_NEGATE]) { + ADDCHAR(c); + something_found =3D 1; + } + else + charset[CURLFNM_NEGATE] =3D 1; /* negate charset */ + } + else + ADDCHAR(c); + (*p)++; + } + else if(c =3D=3D '\\') { + c =3D *(++(*p)); + if(ISPRINT((c))) { + something_found =3D TRUE; + state =3D CURLFNM_SCHS_MAYRANGE; + ADDCHAR(c); + rangestart =3D c; + (*p)++; + } + else + return SETCHARSET_FAIL; + } + else if(c =3D=3D '\0') { + return SETCHARSET_FAIL; + } + else { + ADDCHAR(c); + (*p)++; + something_found =3D TRUE; + } + break; + case CURLFNM_SCHS_MAYRANGE: + if(c =3D=3D '-'){ + ADDCHAR(c); + (*p)++; + lastchar =3D '-'; + state =3D CURLFNM_SCHS_MAYRANGE2; + } + else if(c =3D=3D '[') { + state =3D CURLFNM_SCHS_DEFAULT; + } + else if(ISALNUM(c)) { + ADDCHAR(c); + (*p)++; + } + else if(c =3D=3D '\\') { + c =3D *(++(*p)); + if(isprint(c)) { + ADDCHAR(c); + (*p)++; + } + else + return SETCHARSET_FAIL; + } + else if(c =3D=3D ']') { + return SETCHARSET_OK; + } + else + return SETCHARSET_FAIL; + break; + case CURLFNM_SCHS_MAYRANGE2: + if(c =3D=3D '\\') { + c =3D *(++(*p)); + if(!ISPRINT(c)) + return SETCHARSET_FAIL; + } + if(c =3D=3D ']') { + return SETCHARSET_OK; + } + else if(c =3D=3D '\\') { + c =3D *(++(*p)); + if(ISPRINT(c)) { + ADDCHAR(c); + state =3D CURLFNM_SCHS_DEFAULT; + (*p)++; + } + else + return SETCHARSET_FAIL; + } + if(c >=3D rangestart) { + if((ISLOWER(c) && ISLOWER(rangestart)) || + (ISDIGIT(c) && ISDIGIT(rangestart)) || + (ISUPPER(c) && ISUPPER(rangestart))) { + REMCHAR(lastchar); + rangestart++; + while(rangestart++ <=3D c) + ADDCHAR(rangestart-1); + (*p)++; + state =3D CURLFNM_SCHS_DEFAULT; + } + else + return SETCHARSET_FAIL; + } + break; + case CURLFNM_SCHS_RIGHTBR: + if(c =3D=3D '[') { + state =3D CURLFNM_SCHS_RIGHTBRLEFTBR; + ADDCHAR(c); + (*p)++; + } + else if(c =3D=3D ']') { + return SETCHARSET_OK; + } + else if(c =3D=3D '\0') { + return SETCHARSET_FAIL; + } + break; + case CURLFNM_SCHS_RIGHTBRLEFTBR: + if(c =3D=3D ']') { + return SETCHARSET_OK; + } + else if(c =3D=3D '[') { + state =3D CURLFNM_SCHS_DEFAULT; + ADDCHAR(c); + (*p)++; + } + break; + } + } + return SETCHARSET_FAIL; +} + +static int loop(const unsigned char *pattern, const unsigned char *stri= ng) +{ + loop_state state =3D CURLFNM_LOOP_DEFAULT; + register unsigned char *p =3D (unsigned char *)pattern; + register unsigned char *s =3D (unsigned char *)string; + unsigned char charset[CURLFNM_CHSET_SIZE] =3D { 0 }; + int rc =3D 0; + + for (;;) { + switch(state) { + case CURLFNM_LOOP_DEFAULT: + if(*p =3D=3D '*') { + while(*(p+1) =3D=3D '*') /* eliminate multiple stars */ + p++; + if(*s =3D=3D '\0' && *(p+1) =3D=3D '\0') + return CURL_FNMATCH_MATCH; + rc =3D loop(p + 1, s); /* *.txt matches .txt <=3D> .txt matches= .txt */ + if(rc =3D=3D CURL_FNMATCH_MATCH) + return CURL_FNMATCH_MATCH; + if(*s) /* let the star eat up one character */ + s++; + else + return CURL_FNMATCH_NOMATCH; + } + else if(*p =3D=3D '?') { + if(ISPRINT(*s)) { + s++; + p++; + } + else if(*s =3D=3D '\0') + return CURL_FNMATCH_NOMATCH; + else + return CURL_FNMATCH_FAIL; /* cannot deal with other character= */ + } + else if(*p =3D=3D '\0') { + if(*s =3D=3D '\0') + return CURL_FNMATCH_MATCH; + else + return CURL_FNMATCH_NOMATCH; + } + else if(*p =3D=3D '\\') { + state =3D CURLFNM_LOOP_BACKSLASH; + p++; + } + else if(*p =3D=3D '[') { + unsigned char *pp =3D p+1; /* cannot handle with pointer to reg= ister */ + if(setcharset(&pp, charset)) { + bool found =3D FALSE; + if(charset[(unsigned int)*s]) + found =3D TRUE; + else if(charset[CURLFNM_ALNUM]) + found =3D ISALNUM(*s); + else if(charset[CURLFNM_ALPHA]) + found =3D ISALPHA(*s); + else if(charset[CURLFNM_DIGIT]) + found =3D ISDIGIT(*s); + else if(charset[CURLFNM_XDIGIT]) + found =3D ISXDIGIT(*s); + else if(charset[CURLFNM_PRINT]) + found =3D ISPRINT(*s); + else if(charset[CURLFNM_SPACE]) + found =3D ISSPACE(*s); + else if(charset[CURLFNM_UPPER]) + found =3D ISUPPER(*s); + else if(charset[CURLFNM_LOWER]) + found =3D ISLOWER(*s); + else if(charset[CURLFNM_BLANK]) + found =3D ISBLANK(*s); + else if(charset[CURLFNM_GRAPH]) + found =3D ISGRAPH(*s); + + if(charset[CURLFNM_NEGATE]) + found =3D !found; + + if(found) { + p =3D pp+1; + s++; + memset(charset, 0, CURLFNM_CHSET_SIZE); + } + else + return CURL_FNMATCH_NOMATCH; + } + else + return CURL_FNMATCH_FAIL; + } + else { + if(*p++ !=3D *s++) + return CURL_FNMATCH_NOMATCH; + } + break; + case CURLFNM_LOOP_BACKSLASH: + if(ISPRINT(*p)) { + if(*p++ =3D=3D *s++) + state =3D CURLFNM_LOOP_DEFAULT; + else + return CURL_FNMATCH_NOMATCH; + } + else + return CURL_FNMATCH_FAIL; + break; + } + } +} + +int Curl_fnmatch(const char *pattern, const char *string) +{ + if(!pattern || !string) { + return CURL_FNMATCH_FAIL; + } + return loop((unsigned char *)pattern, (unsigned char *)string); +} diff --git a/lib/curl_fnmatch.h b/lib/curl_fnmatch.h new file mode 100644 index 0000000..4bec4fe --- /dev/null +++ b/lib/curl_fnmatch.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_FNMATCH_H +#define HEADER_CURL_FNMATCH_H +/**********************************************************************= ***** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel_at_haxx.se>, et al.= + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or = sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY O= F ANY + * KIND, either express or implied. + * + **********************************************************************= *****/ + +#define CURL_FNMATCH_MATCH 0 +#define CURL_FNMATCH_NOMATCH 1 +#define CURL_FNMATCH_FAIL 2 + +/* default pattern matching function + * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + * Implemented with recursive backtracking, if you want to use Curl_fnm= atch, + * please note that there is not implemented UTF/UNICODE support. + * + * Implemented features: + * '?' notation, does not match utf characters + * '*' can also work with utf string + * [a-zA-Z0-9] enumeration support + * + * keywords: alnum, digit, xdigit, aplpha, print, blank, lower, graph, = space + * and upper (use as "[[:allnum:]]") + */ +int Curl_fnmatch(const char *pattern, const char *string); + +#endif /* HEADER_CURL_FNMATCH_H */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index b28c5ad..23dc98f 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -65,7 +65,8 @@ EXTRA_DIST =3D test1 test108 test117 test127 test20 te= st27 test34 test46 \ test564 test1101 test1102 test1103 test1104 test299 test310 test311 = \ test312 test1105 test565 test800 test1106 test801 test566 test802 test= 803 \ test1107 test1108 test1109 test1110 test1111 test1112 test129 test567 = \ - test568 test569 test570 test571 test572 test804 test805 test806 test80= 7 + test568 test569 test570 test571 test572 test804 test805 test806 test80= 7 \ + test573 = filecheck: @mkdir test-place; \ diff --git a/tests/data/test573 b/tests/data/test573 new file mode 100644 index 0000000..434ba88 --- /dev/null +++ b/tests/data/test573 @@ -0,0 +1,36 @@ +<testcase> +# +# Server-side +<reply> +</reply> + +# Client-side +<client> +<server> +none +</server> +# tool is what to use instead of 'curl' +<tool> +lib573 +</tool> + + <name> +Curl_fnmatch() testing + </name> + <command> +nothing +</command> +</client> + +# +# Verify data after the test has been "shot" +<verify> +<stdout mode=3D"text"> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D +</stdout> +<valgrind> +disable +</valgrind> +</verify> +</testcase> diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index 4dc8615..4479e29 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -11,7 +11,7 @@ noinst_PROGRAMS =3D lib500 lib501 lib502 lib503 lib504= lib505 lib506 \ lib529 lib530 lib532 lib533 lib536 lib537 lib540 lib541 lib542 lib543= \ lib544 lib545 lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556= \ lib539 lib557 lib558 lib559 lib560 lib562 lib564 lib565 lib566 lib567= \ - lib568 lib569 lib570 lib571 lib572 + lib568 lib569 lib570 lib571 lib572 lib573 = lib500_SOURCES =3D lib500.c $(SUPPORTFILES) = @@ -145,3 +145,4 @@ lib571_SOURCES =3D lib571.c $(SUPPORTFILES) = lib572_SOURCES =3D lib572.c $(SUPPORTFILES) = +lib573_SOURCES =3D lib573.c $(SUPPORTFILES) diff --git a/tests/libtest/lib573.c b/tests/libtest/lib573.c new file mode 100644 index 0000000..6e4c7e8 --- /dev/null +++ b/tests/libtest/lib573.c @@ -0,0 +1,211 @@ +/**********************************************************************= ******* + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + */ + +#include "test.h" + +#include "memdebug.h" + +#include "curl_fnmatch.h" + +#define MATCH CURL_FNMATCH_MATCH +#define NOMATCH CURL_FNMATCH_NOMATCH +#define ERROR CURL_FNMATCH_FAIL + +#define MAX_PATTERN_L 100 +#define MAX_STRING_L 100 + +struct testcase { + char pattern[MAX_PATTERN_L]; + char string[MAX_STRING_L]; + int result; +}; + +static const struct testcase tests[] =3D { + /* brackets syntax */ + { "\\[", "[", MATCH }, + { "[", "[", ERROR }, + { "[]", "[]", ERROR }, + { "[][]", "[", MATCH }, + { "[][]", "]", MATCH }, + { "[[]", "[", MATCH }, + { "[[[]", "[", MATCH }, + { "[[[[]", "[", MATCH }, + { "[[[[]", "[", MATCH }, + + { "[][[]", "]", MATCH }, + { "[][[[]", "[", MATCH }, + { "[[]", "]", NOMATCH }, + + { "[a-z]", "a", MATCH }, + { "[a-z]", "A", NOMATCH }, + { "?[a-z]", "?Z", NOMATCH }, + { "[A-Z]", "C", MATCH }, + { "[A-Z]", "c", NOMATCH }, + { "[0-9]", "7", MATCH }, + { "[7-8]", "7", MATCH }, + { "[7-]", "7", MATCH }, + { "[7-]", "-", MATCH }, + { "[7-]", "[", NOMATCH }, + { "[a-bA-F]", "F", MATCH }, + { "[a-bA-B9]", "9", MATCH }, + { "[a-bA-B98]", "8", MATCH }, + { "[a-bA-B98]", "C", NOMATCH }, + { "[a-bA-Z9]", "F", MATCH }, + { "[a-bA-Z9]ero*", "Zero chance.", MATCH }, + { "S[a-][x]opho*", "Saxophone", MATCH }, + { "S[a-][x]opho*", "SaXophone", NOMATCH }, + { "S[a-][x]*.txt", "S-x.txt", MATCH }, + { "[\\a-\\b]", "a", MATCH }, + { "[\\a-\\b]", "b", MATCH }, + { "[?*[][?*[][?*[]", "?*[", MATCH }, + { "?/b/c", "a/b/c", MATCH }, + { "^_{}~", "^_{}~", MATCH }, + { "!#%+,-./01234567889", "!#%+,-./01234567889", MATCH }, + { "PQRSTUVWXYZ]abcdefg", "PQRSTUVWXYZ]abcdefg", MATCH }, + { ":;=3D_at_ABCDEFGHIJKLMNO", ":;=3D_at_ABCDEFGHIJKLMNO", MATCH }, + + /* negate */ + { "[!a]", "b", MATCH }, + { "[!a]", "a", NOMATCH }, + { "[^a]", "b", MATCH }, + { "[^a]", "a", NOMATCH }, + { "[^a-z0-9A-Z]", "a", NOMATCH }, + { "[^a-z0-9A-Z]", "-", MATCH }, + { "curl[!a-z]lib", "curl lib", MATCH }, + { "curl[! ]lib", "curl lib", NOMATCH }, + { "[! ][ ]", " ", NOMATCH }, + { "[! ][ ]", "a ", MATCH }, + { "*[^a].t?t", "a.txt", NOMATCH }, + { "*[^a].t?t", "ba.txt", NOMATCH }, + { "*[^a].t?t", "ab.txt", MATCH }, + { "[!?*[]", "?", NOMATCH }, + { "[!!]", "!", NOMATCH }, + { "[!!]", "x", MATCH }, + + { "[[:alpha:]]", "a", MATCH }, + { "[[:alpha:]]", "9", NOMATCH }, + { "[[:alnum:]]", "a", MATCH }, + { "[[:alnum:]]", "[", NOMATCH }, + { "[[:alnum:]]", "]", NOMATCH }, + { "[[:alnum:]]", "9", MATCH }, + { "[[:digit:]]", "9", MATCH }, + { "[[:xdigit:]]", "9", MATCH }, + { "[[:xdigit:]]", "F", MATCH }, + { "[[:xdigit:]]", "G", NOMATCH }, + { "[[:upper:]]", "U", MATCH }, + { "[[:upper:]]", "u", NOMATCH }, + { "[[:lower:]]", "l", MATCH }, + { "[[:lower:]]", "L", NOMATCH }, + { "[[:print:]]", "L", MATCH }, + { "[[:print:]]", {'\10'}, NOMATCH }, + { "[[:print:]]", {'\10'}, NOMATCH }, + { "[[:space:]]", " ", MATCH }, + { "[[:space:]]", "x", NOMATCH }, + { "[[:graph:]]", " ", NOMATCH }, + { "[[:graph:]]", "x", MATCH }, + { "[[:blank:]]", {'\t'}, MATCH }, + { "[[:blank:]]", {' '}, MATCH }, + { "[[:blank:]]", {'\r'}, NOMATCH }, + { "[^[:blank:]]", {'\t'}, NOMATCH }, + { "[^[:print:]]", {'\10'}, MATCH }, + { "[[:lower:]][[:lower:]]", "ll", MATCH }, + + { "Curl[[:blank:]];-)", "Curl ;-)", MATCH }, + { "*[[:blank:]]*", " ", MATCH }, + { "*[[:blank:]]*", "", NOMATCH }, + { "*[[:blank:]]*", "hi, im_Pavel", MATCH }, + + /* common using */ + { "filename.dat", "filename.dat", MATCH }, + { "*curl*", "lets use curl!!", MATCH }, + { "filename.txt", "filename.dat", NOMATCH }, + { "*.txt", "text.txt", MATCH }, + { "*.txt", "a.txt", MATCH }, + { "*.txt", ".txt", MATCH }, + { "*.txt", "txt", NOMATCH }, + { "??.txt", "99.txt", MATCH }, + { "??.txt", "a99.txt", NOMATCH }, + { "?.???", "a.txt", MATCH }, + { "*.???", "somefile.dat", MATCH }, + { "*.???", "photo.jpeg", NOMATCH }, + { ".*", ".htaccess", MATCH }, + { ".*", ".", MATCH }, + { ".*", "..", MATCH }, + + /* many stars =3D> one star */ + { "**.txt", "text.txt", MATCH }, + { "***.txt", "t.txt", MATCH }, + { "****.txt", ".txt", MATCH }, + + /* empty string or pattern */ + { "", "", MATCH } , + { "", "hello", NOMATCH }, + { "file", "", NOMATCH }, + { "?", "", NOMATCH }, + { "*", "", MATCH }, + { "x", "", NOMATCH }, + + /* backslash */ + { "\\", "\\", ERROR }, + { "\\\\", "\\", MATCH }, + { "\\\\", "\\\\", NOMATCH }, + { "\\?", "?", MATCH }, + { "\\*", "*", MATCH }, + { "?.txt", "?.txt", MATCH }, + { "*.txt", "*.txt", MATCH }, + { "\\?.txt", "?.txt", MATCH }, + { "\\*.txt", "*.txt", MATCH }, + { "\\?.txt", "x.txt", NOMATCH }, + { "\\*.txt", "x.txt", NOMATCH }, + { "\\*\\\\.txt", "*\\.txt", MATCH }, + { "*\\**\\?*\\\\*", "cc*cc?cc\\cc*cc", MATCH }, + { "*\\**\\?*\\\\*", "cc*cc?cccc", NOMATCH }, + { "*\\**\\?*\\\\*", "cc*cc?cc\\cc*cc", MATCH }, + { "*\\?*\\**", "cc?c*c", MATCH }, + { "*\\?*\\**curl*", "cc?c*curl", MATCH }, + { "*\\?*\\**", "cc?cc", NOMATCH }, + { "\\\"\\$\\&\\'\\(\\)", "\"$&'()", MATCH }, + { "\\*\\?\\[\\\\\\`\\|", "*?[\\`|", MATCH }, + { "[\\a\\b]c", "ac", MATCH }, + { "[\\a\\b]c", "bc", MATCH }, + { "[\\a\\b]d", "bc", NOMATCH }, + { "[a-bA-B\\?]", "?", MATCH }, + { "cu[a-ab-b\\r]l", "curl", MATCH }, + { "[\\a-z]", "c", MATCH }, + + { "?*?*?.*?*", "abc.c", MATCH }, + { "?*?*?.*?*", "abcc", NOMATCH }, + { "?*?*?.*?*", "abc.", NOMATCH }, + { "?*?*?.*?*", "abc.c++", MATCH }, + { "?*?*?.*?*", "abcdef.c++", MATCH }, + { "?*?*?.?", "abcdef.c", MATCH }, + { "?*?*?.?", "abcdef.cd", NOMATCH }, + + { "Lindm=C3=A4tarv", "Lindm=C3=A4tarv", MAT= CH }, + + { "", "", MATCH } +}; + + +int test(char *URL) +{ + int testnum =3D sizeof(tests) / sizeof(struct testcase); + int i, rc; + (void)URL; /* not used */ + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D\n"); + for(i =3D 0; i < testnum; i++) { + rc =3D Curl_fnmatch(tests[i].pattern, tests[i].string); + if(rc !=3D tests[i].result) { + printf("Curl_fnmatch(\"%s\", \"%s\") should return %d (returns %d= )\n", + tests[i].pattern, tests[i].string, tests[i].result, rc); + } + } + printf("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D\n"); + return 0; +} -- = 1.7.0 ------------H7Zxg5ktxBmXd1VKCWfEXb Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html ------------H7Zxg5ktxBmXd1VKCWfEXb--Received on 2001-09-17