Fossil SCM
Enhance the GLOB processing on settings like binary-glob so that any sequence of commas and/or whitespace serves as a delimiter. Delimiters inside of quotes are part the glob pattern and are ignored. Enhance the test-glob command to verify correct operation of the globber.
Commit
a93b58cf83ce00d069fbbd99bc6aa6cc51e3fa65
Parent
2d9ae4ee73f7223…
2 files changed
+40
-24
+118
+40
-24
| --- src/glob.c | ||
| +++ src/glob.c | ||
| @@ -29,16 +29,17 @@ | ||
| 29 | 29 | ** zVal: "x" |
| 30 | 30 | ** zGlobList: "*.o,*.obj" |
| 31 | 31 | ** |
| 32 | 32 | ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')" |
| 33 | 33 | ** |
| 34 | -** Each element of the GLOB list may optionally be enclosed in either '...' | |
| 35 | -** or "...". This allows commas in the expression. Whitespace at the | |
| 36 | -** beginning and end of each GLOB pattern is ignored, except when enclosed | |
| 37 | -** within '...' or "...". | |
| 34 | +** Commas and whitespace are considered to be element delimters. Each | |
| 35 | +** element of the GLOB list may optionally be enclosed in either '...' or | |
| 36 | +** "...". This allows commas and/or whitespace to be used in the elements | |
| 37 | +** themselves. | |
| 38 | 38 | ** |
| 39 | -** This routine makes no effort to free the memory space it uses. | |
| 39 | +** This routine makes no effort to free the memory space it uses, which | |
| 40 | +** currently consists of a blob object and its contents. | |
| 40 | 41 | */ |
| 41 | 42 | char *glob_expr(const char *zVal, const char *zGlobList){ |
| 42 | 43 | Blob expr; |
| 43 | 44 | char *zSep = "("; |
| 44 | 45 | int nTerm = 0; |
| @@ -46,21 +47,24 @@ | ||
| 46 | 47 | int cTerm; |
| 47 | 48 | |
| 48 | 49 | if( zGlobList==0 || zGlobList[0]==0 ) return "0"; |
| 49 | 50 | blob_zero(&expr); |
| 50 | 51 | while( zGlobList[0] ){ |
| 51 | - while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++; | |
| 52 | + while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ){ | |
| 53 | + zGlobList++; /* Skip leading commas, spaces, and newlines */ | |
| 54 | + } | |
| 52 | 55 | if( zGlobList[0]==0 ) break; |
| 53 | 56 | if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){ |
| 54 | 57 | cTerm = zGlobList[0]; |
| 55 | 58 | zGlobList++; |
| 56 | 59 | }else{ |
| 57 | 60 | cTerm = ','; |
| 58 | 61 | } |
| 59 | - for(i=0; zGlobList[i] && zGlobList[i]!=cTerm && zGlobList[i]!='\n'; i++){} | |
| 60 | - if( cTerm==',' ){ | |
| 61 | - while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; } | |
| 62 | + /* Find the next delimter (or the end of the string). */ | |
| 63 | + for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){ | |
| 64 | + if( cTerm!=',' ) continue; /* If quoted, keep going. */ | |
| 65 | + if( fossil_isspace(zGlobList[i]) ) break; /* If space, stop. */ | |
| 62 | 66 | } |
| 63 | 67 | blob_appendf(&expr, "%s%s GLOB '%#q'", zSep, zVal, i, zGlobList); |
| 64 | 68 | zSep = " OR "; |
| 65 | 69 | if( cTerm!=',' && zGlobList[i] ) i++; |
| 66 | 70 | zGlobList += i; |
| @@ -85,24 +89,24 @@ | ||
| 85 | 89 | char **azPattern; /* Array of pointers to patterns */ |
| 86 | 90 | }; |
| 87 | 91 | #endif /* INTERFACE */ |
| 88 | 92 | |
| 89 | 93 | /* |
| 90 | -** zPatternList is a comma-separate list of glob patterns. Parse up | |
| 94 | +** zPatternList is a comma-separated list of glob patterns. Parse up | |
| 91 | 95 | ** that list and use it to create a new Glob object. |
| 92 | 96 | ** |
| 93 | 97 | ** Elements of the glob list may be optionally enclosed in single our |
| 94 | -** double-quotes. This allows a comma to be part of a glob. | |
| 98 | +** double-quotes. This allows a comma to be part of a glob pattern. | |
| 95 | 99 | ** |
| 96 | 100 | ** Leading and trailing spaces on unquoted glob patterns are ignored. |
| 97 | 101 | ** |
| 98 | 102 | ** An empty or null pattern list results in a null glob, which will |
| 99 | 103 | ** match nothing. |
| 100 | 104 | */ |
| 101 | 105 | Glob *glob_create(const char *zPatternList){ |
| 102 | 106 | int nList; /* Size of zPatternList in bytes */ |
| 103 | - int i, j; /* Loop counters */ | |
| 107 | + int i; /* Loop counters */ | |
| 104 | 108 | Glob *p; /* The glob being created */ |
| 105 | 109 | char *z; /* Copy of the pattern list */ |
| 106 | 110 | char delimiter; /* '\'' or '\"' or 0 */ |
| 107 | 111 | |
| 108 | 112 | if( zPatternList==0 || zPatternList[0]==0 ) return 0; |
| @@ -110,27 +114,26 @@ | ||
| 110 | 114 | p = fossil_malloc( sizeof(*p) + nList+1 ); |
| 111 | 115 | memset(p, 0, sizeof(*p)); |
| 112 | 116 | z = (char*)&p[1]; |
| 113 | 117 | memcpy(z, zPatternList, nList+1); |
| 114 | 118 | while( z[0] ){ |
| 115 | - while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ){ | |
| 116 | - z++; /* Skip leading spaces and newlines */ | |
| 119 | + while( fossil_isspace(z[0]) || z[0]==',' ){ | |
| 120 | + z++; /* Skip leading commas, spaces, and newlines */ | |
| 117 | 121 | } |
| 122 | + if( z[0]==0 ) break; | |
| 118 | 123 | if( z[0]=='\'' || z[0]=='"' ){ |
| 119 | 124 | delimiter = z[0]; |
| 120 | 125 | z++; |
| 121 | 126 | }else{ |
| 122 | 127 | delimiter = ','; |
| 123 | 128 | } |
| 124 | - if( z[0]==0 ) break; | |
| 125 | 129 | p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) ); |
| 126 | 130 | p->azPattern[p->nPattern++] = z; |
| 127 | - for(i=0; z[i] && z[i]!=delimiter && z[i]!='\n' && z[i]!='\r'; i++){} | |
| 128 | - if( delimiter==',' ){ | |
| 129 | - /* Remove trailing spaces / newlines on a comma-delimited pattern */ | |
| 130 | - for(j=i; j>1 && (z[j-1]==' ' || z[j-1]=='\n' || z[j-1]=='\r'); j--){} | |
| 131 | - if( j<i ) z[j] = 0; | |
| 131 | + /* Find the next delimter (or the end of the string). */ | |
| 132 | + for(i=0; z[i] && z[i]!=delimiter; i++){ | |
| 133 | + if( delimiter!=',' ) continue; /* If quoted, keep going. */ | |
| 134 | + if( fossil_isspace(z[i]) ) break; /* If space, stop. */ | |
| 132 | 135 | } |
| 133 | 136 | if( z[i]==0 ) break; |
| 134 | 137 | z[i] = 0; |
| 135 | 138 | z += i+1; |
| 136 | 139 | } |
| @@ -245,22 +248,35 @@ | ||
| 245 | 248 | /* |
| 246 | 249 | ** COMMAND: test-glob |
| 247 | 250 | ** |
| 248 | 251 | ** Usage: %fossil test-glob PATTERN STRING... |
| 249 | 252 | ** |
| 250 | -** PATTERN is a comma-separated list of glob patterns. Show which of | |
| 251 | -** the STRINGs that follow match the PATTERN. | |
| 253 | +** PATTERN is a comma- and whitespace-separated list of optionally | |
| 254 | +** quoted glob patterns. Show which of the STRINGs that follow match | |
| 255 | +** the PATTERN. | |
| 256 | +** | |
| 257 | +** If PATTERN begins with "@" the the rest of the pattern is understood | |
| 258 | +** to be a setting name (such as binary-glob, crln-glob, or encoding-glob) | |
| 259 | +** and the value of that setting is used as the actually glob pattern. | |
| 252 | 260 | */ |
| 253 | 261 | void glob_test_cmd(void){ |
| 254 | 262 | Glob *pGlob; |
| 255 | 263 | int i; |
| 264 | + char *zPattern; | |
| 256 | 265 | if( g.argc<4 ) usage("PATTERN STRING ..."); |
| 257 | - fossil_print("SQL expression: %s\n", glob_expr("x", g.argv[2])); | |
| 258 | - pGlob = glob_create(g.argv[2]); | |
| 266 | + zPattern = g.argv[2]; | |
| 267 | + if( zPattern[0]=='@' ){ | |
| 268 | + db_find_and_open_repository(OPEN_ANY_SCHEMA,0); | |
| 269 | + zPattern = db_get(zPattern+1, 0); | |
| 270 | + if( zPattern==0 ) fossil_fatal("no such setting: %s", g.argv[2]+1); | |
| 271 | + fossil_print("GLOB pattern: %s\n", zPattern); | |
| 272 | + } | |
| 273 | + fossil_print("SQL expression: %s\n", glob_expr("x", zPattern)); | |
| 274 | + pGlob = glob_create(zPattern); | |
| 259 | 275 | for(i=0; i<pGlob->nPattern; i++){ |
| 260 | 276 | fossil_print("pattern[%d] = [%s]\n", i, pGlob->azPattern[i]); |
| 261 | 277 | } |
| 262 | 278 | for(i=3; i<g.argc; i++){ |
| 263 | 279 | fossil_print("%d %s\n", glob_match(pGlob, g.argv[i]), g.argv[i]); |
| 264 | 280 | } |
| 265 | 281 | glob_free(pGlob); |
| 266 | 282 | } |
| 267 | 283 | |
| 268 | 284 | ADDED test/glob.test |
| --- src/glob.c | |
| +++ src/glob.c | |
| @@ -29,16 +29,17 @@ | |
| 29 | ** zVal: "x" |
| 30 | ** zGlobList: "*.o,*.obj" |
| 31 | ** |
| 32 | ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')" |
| 33 | ** |
| 34 | ** Each element of the GLOB list may optionally be enclosed in either '...' |
| 35 | ** or "...". This allows commas in the expression. Whitespace at the |
| 36 | ** beginning and end of each GLOB pattern is ignored, except when enclosed |
| 37 | ** within '...' or "...". |
| 38 | ** |
| 39 | ** This routine makes no effort to free the memory space it uses. |
| 40 | */ |
| 41 | char *glob_expr(const char *zVal, const char *zGlobList){ |
| 42 | Blob expr; |
| 43 | char *zSep = "("; |
| 44 | int nTerm = 0; |
| @@ -46,21 +47,24 @@ | |
| 46 | int cTerm; |
| 47 | |
| 48 | if( zGlobList==0 || zGlobList[0]==0 ) return "0"; |
| 49 | blob_zero(&expr); |
| 50 | while( zGlobList[0] ){ |
| 51 | while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ) zGlobList++; |
| 52 | if( zGlobList[0]==0 ) break; |
| 53 | if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){ |
| 54 | cTerm = zGlobList[0]; |
| 55 | zGlobList++; |
| 56 | }else{ |
| 57 | cTerm = ','; |
| 58 | } |
| 59 | for(i=0; zGlobList[i] && zGlobList[i]!=cTerm && zGlobList[i]!='\n'; i++){} |
| 60 | if( cTerm==',' ){ |
| 61 | while( i>0 && fossil_isspace(zGlobList[i-1]) ){ i--; } |
| 62 | } |
| 63 | blob_appendf(&expr, "%s%s GLOB '%#q'", zSep, zVal, i, zGlobList); |
| 64 | zSep = " OR "; |
| 65 | if( cTerm!=',' && zGlobList[i] ) i++; |
| 66 | zGlobList += i; |
| @@ -85,24 +89,24 @@ | |
| 85 | char **azPattern; /* Array of pointers to patterns */ |
| 86 | }; |
| 87 | #endif /* INTERFACE */ |
| 88 | |
| 89 | /* |
| 90 | ** zPatternList is a comma-separate list of glob patterns. Parse up |
| 91 | ** that list and use it to create a new Glob object. |
| 92 | ** |
| 93 | ** Elements of the glob list may be optionally enclosed in single our |
| 94 | ** double-quotes. This allows a comma to be part of a glob. |
| 95 | ** |
| 96 | ** Leading and trailing spaces on unquoted glob patterns are ignored. |
| 97 | ** |
| 98 | ** An empty or null pattern list results in a null glob, which will |
| 99 | ** match nothing. |
| 100 | */ |
| 101 | Glob *glob_create(const char *zPatternList){ |
| 102 | int nList; /* Size of zPatternList in bytes */ |
| 103 | int i, j; /* Loop counters */ |
| 104 | Glob *p; /* The glob being created */ |
| 105 | char *z; /* Copy of the pattern list */ |
| 106 | char delimiter; /* '\'' or '\"' or 0 */ |
| 107 | |
| 108 | if( zPatternList==0 || zPatternList[0]==0 ) return 0; |
| @@ -110,27 +114,26 @@ | |
| 110 | p = fossil_malloc( sizeof(*p) + nList+1 ); |
| 111 | memset(p, 0, sizeof(*p)); |
| 112 | z = (char*)&p[1]; |
| 113 | memcpy(z, zPatternList, nList+1); |
| 114 | while( z[0] ){ |
| 115 | while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ){ |
| 116 | z++; /* Skip leading spaces and newlines */ |
| 117 | } |
| 118 | if( z[0]=='\'' || z[0]=='"' ){ |
| 119 | delimiter = z[0]; |
| 120 | z++; |
| 121 | }else{ |
| 122 | delimiter = ','; |
| 123 | } |
| 124 | if( z[0]==0 ) break; |
| 125 | p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) ); |
| 126 | p->azPattern[p->nPattern++] = z; |
| 127 | for(i=0; z[i] && z[i]!=delimiter && z[i]!='\n' && z[i]!='\r'; i++){} |
| 128 | if( delimiter==',' ){ |
| 129 | /* Remove trailing spaces / newlines on a comma-delimited pattern */ |
| 130 | for(j=i; j>1 && (z[j-1]==' ' || z[j-1]=='\n' || z[j-1]=='\r'); j--){} |
| 131 | if( j<i ) z[j] = 0; |
| 132 | } |
| 133 | if( z[i]==0 ) break; |
| 134 | z[i] = 0; |
| 135 | z += i+1; |
| 136 | } |
| @@ -245,22 +248,35 @@ | |
| 245 | /* |
| 246 | ** COMMAND: test-glob |
| 247 | ** |
| 248 | ** Usage: %fossil test-glob PATTERN STRING... |
| 249 | ** |
| 250 | ** PATTERN is a comma-separated list of glob patterns. Show which of |
| 251 | ** the STRINGs that follow match the PATTERN. |
| 252 | */ |
| 253 | void glob_test_cmd(void){ |
| 254 | Glob *pGlob; |
| 255 | int i; |
| 256 | if( g.argc<4 ) usage("PATTERN STRING ..."); |
| 257 | fossil_print("SQL expression: %s\n", glob_expr("x", g.argv[2])); |
| 258 | pGlob = glob_create(g.argv[2]); |
| 259 | for(i=0; i<pGlob->nPattern; i++){ |
| 260 | fossil_print("pattern[%d] = [%s]\n", i, pGlob->azPattern[i]); |
| 261 | } |
| 262 | for(i=3; i<g.argc; i++){ |
| 263 | fossil_print("%d %s\n", glob_match(pGlob, g.argv[i]), g.argv[i]); |
| 264 | } |
| 265 | glob_free(pGlob); |
| 266 | } |
| 267 | |
| 268 | DDED test/glob.test |
| --- src/glob.c | |
| +++ src/glob.c | |
| @@ -29,16 +29,17 @@ | |
| 29 | ** zVal: "x" |
| 30 | ** zGlobList: "*.o,*.obj" |
| 31 | ** |
| 32 | ** Result: "(x GLOB '*.o' OR x GLOB '*.obj')" |
| 33 | ** |
| 34 | ** Commas and whitespace are considered to be element delimters. Each |
| 35 | ** element of the GLOB list may optionally be enclosed in either '...' or |
| 36 | ** "...". This allows commas and/or whitespace to be used in the elements |
| 37 | ** themselves. |
| 38 | ** |
| 39 | ** This routine makes no effort to free the memory space it uses, which |
| 40 | ** currently consists of a blob object and its contents. |
| 41 | */ |
| 42 | char *glob_expr(const char *zVal, const char *zGlobList){ |
| 43 | Blob expr; |
| 44 | char *zSep = "("; |
| 45 | int nTerm = 0; |
| @@ -46,21 +47,24 @@ | |
| 47 | int cTerm; |
| 48 | |
| 49 | if( zGlobList==0 || zGlobList[0]==0 ) return "0"; |
| 50 | blob_zero(&expr); |
| 51 | while( zGlobList[0] ){ |
| 52 | while( fossil_isspace(zGlobList[0]) || zGlobList[0]==',' ){ |
| 53 | zGlobList++; /* Skip leading commas, spaces, and newlines */ |
| 54 | } |
| 55 | if( zGlobList[0]==0 ) break; |
| 56 | if( zGlobList[0]=='\'' || zGlobList[0]=='"' ){ |
| 57 | cTerm = zGlobList[0]; |
| 58 | zGlobList++; |
| 59 | }else{ |
| 60 | cTerm = ','; |
| 61 | } |
| 62 | /* Find the next delimter (or the end of the string). */ |
| 63 | for(i=0; zGlobList[i] && zGlobList[i]!=cTerm; i++){ |
| 64 | if( cTerm!=',' ) continue; /* If quoted, keep going. */ |
| 65 | if( fossil_isspace(zGlobList[i]) ) break; /* If space, stop. */ |
| 66 | } |
| 67 | blob_appendf(&expr, "%s%s GLOB '%#q'", zSep, zVal, i, zGlobList); |
| 68 | zSep = " OR "; |
| 69 | if( cTerm!=',' && zGlobList[i] ) i++; |
| 70 | zGlobList += i; |
| @@ -85,24 +89,24 @@ | |
| 89 | char **azPattern; /* Array of pointers to patterns */ |
| 90 | }; |
| 91 | #endif /* INTERFACE */ |
| 92 | |
| 93 | /* |
| 94 | ** zPatternList is a comma-separated list of glob patterns. Parse up |
| 95 | ** that list and use it to create a new Glob object. |
| 96 | ** |
| 97 | ** Elements of the glob list may be optionally enclosed in single our |
| 98 | ** double-quotes. This allows a comma to be part of a glob pattern. |
| 99 | ** |
| 100 | ** Leading and trailing spaces on unquoted glob patterns are ignored. |
| 101 | ** |
| 102 | ** An empty or null pattern list results in a null glob, which will |
| 103 | ** match nothing. |
| 104 | */ |
| 105 | Glob *glob_create(const char *zPatternList){ |
| 106 | int nList; /* Size of zPatternList in bytes */ |
| 107 | int i; /* Loop counters */ |
| 108 | Glob *p; /* The glob being created */ |
| 109 | char *z; /* Copy of the pattern list */ |
| 110 | char delimiter; /* '\'' or '\"' or 0 */ |
| 111 | |
| 112 | if( zPatternList==0 || zPatternList[0]==0 ) return 0; |
| @@ -110,27 +114,26 @@ | |
| 114 | p = fossil_malloc( sizeof(*p) + nList+1 ); |
| 115 | memset(p, 0, sizeof(*p)); |
| 116 | z = (char*)&p[1]; |
| 117 | memcpy(z, zPatternList, nList+1); |
| 118 | while( z[0] ){ |
| 119 | while( fossil_isspace(z[0]) || z[0]==',' ){ |
| 120 | z++; /* Skip leading commas, spaces, and newlines */ |
| 121 | } |
| 122 | if( z[0]==0 ) break; |
| 123 | if( z[0]=='\'' || z[0]=='"' ){ |
| 124 | delimiter = z[0]; |
| 125 | z++; |
| 126 | }else{ |
| 127 | delimiter = ','; |
| 128 | } |
| 129 | p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) ); |
| 130 | p->azPattern[p->nPattern++] = z; |
| 131 | /* Find the next delimter (or the end of the string). */ |
| 132 | for(i=0; z[i] && z[i]!=delimiter; i++){ |
| 133 | if( delimiter!=',' ) continue; /* If quoted, keep going. */ |
| 134 | if( fossil_isspace(z[i]) ) break; /* If space, stop. */ |
| 135 | } |
| 136 | if( z[i]==0 ) break; |
| 137 | z[i] = 0; |
| 138 | z += i+1; |
| 139 | } |
| @@ -245,22 +248,35 @@ | |
| 248 | /* |
| 249 | ** COMMAND: test-glob |
| 250 | ** |
| 251 | ** Usage: %fossil test-glob PATTERN STRING... |
| 252 | ** |
| 253 | ** PATTERN is a comma- and whitespace-separated list of optionally |
| 254 | ** quoted glob patterns. Show which of the STRINGs that follow match |
| 255 | ** the PATTERN. |
| 256 | ** |
| 257 | ** If PATTERN begins with "@" the the rest of the pattern is understood |
| 258 | ** to be a setting name (such as binary-glob, crln-glob, or encoding-glob) |
| 259 | ** and the value of that setting is used as the actually glob pattern. |
| 260 | */ |
| 261 | void glob_test_cmd(void){ |
| 262 | Glob *pGlob; |
| 263 | int i; |
| 264 | char *zPattern; |
| 265 | if( g.argc<4 ) usage("PATTERN STRING ..."); |
| 266 | zPattern = g.argv[2]; |
| 267 | if( zPattern[0]=='@' ){ |
| 268 | db_find_and_open_repository(OPEN_ANY_SCHEMA,0); |
| 269 | zPattern = db_get(zPattern+1, 0); |
| 270 | if( zPattern==0 ) fossil_fatal("no such setting: %s", g.argv[2]+1); |
| 271 | fossil_print("GLOB pattern: %s\n", zPattern); |
| 272 | } |
| 273 | fossil_print("SQL expression: %s\n", glob_expr("x", zPattern)); |
| 274 | pGlob = glob_create(zPattern); |
| 275 | for(i=0; i<pGlob->nPattern; i++){ |
| 276 | fossil_print("pattern[%d] = [%s]\n", i, pGlob->azPattern[i]); |
| 277 | } |
| 278 | for(i=3; i<g.argc; i++){ |
| 279 | fossil_print("%d %s\n", glob_match(pGlob, g.argv[i]), g.argv[i]); |
| 280 | } |
| 281 | glob_free(pGlob); |
| 282 | } |
| 283 | |
| 284 | DDED test/glob.test |
+118
| --- a/test/glob.test | ||
| +++ b/test/glob.test | ||
| @@ -0,0 +1,118 @@ | ||
| 1 | +# | |
| 2 | +# Copyright (c) 2013 D. Richard Hipp | |
| 3 | +# | |
| 4 | +# This program is free software; you can redistribute it and/or | |
| 5 | +# modify it under the terms of the Simplified BSD License (also | |
| 6 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +# | |
| 8 | +# This program is distributed in the hope that it will be useful, | |
| 9 | +# but without any warranty; without even the implied warranty of | |
| 10 | +# merchantability or fitness for a particular purpose. | |
| 11 | +# | |
| 12 | +# Author contact information: | |
| 13 | +# [email protected] | |
| 14 | +# http://www.hwaci.com/drh/ | |
| 15 | +# | |
| 16 | +############################################################################ | |
| 17 | +# | |
| 18 | +# Test glob pattern parsing | |
| 19 | +# | |
| 20 | + | |
| 21 | + parsing | |
| 22 | +# | |
| 23 | + | |
| 24 | +test_setup "" | |
| 25 | + | |
| 26 | +proc glob-parse {testname args} { | |
| 27 | + set i 1 | |
| 28 | + foreach {pattern string result} $args { | |
| 29 | + fossil test-glob $pattern $string | |
| 30 | + test glob-parse-$testname.$i {$::RESULT eq $result} | |
| 31 | + incr i | |
| 32 | + } | |
| 33 | +} | |
| 34 | + | |
| 35 | +glob-parse 100 test test [string map [list \r\n \n] \ | |
| 36 | +{SQL expression: (x GLOB 'test') | |
| 37 | +pattern[0] = [test] | |
| 38 | +1 t*') | |
| 39 | +pattern[0] = [t*] | |
| 40 | +1 1 test}] | |
| 41 | + | |
| 42 | +glob-parse 101 "one two" one [string map [list \r\n \n] \ | |
| 43 | +{SQL expression: (x GLOB 'one' OR x GLOB 'two') | |
| 44 | +pattern[0] = 0 two one}] | |
| 45 | + | |
| 46 | +glob-p02 t* test-parse 108 "\"o*\rtwo\" \"thrt*# | |
| 47 | +# Copyright (c)# | |
| 48 | +# 1 test}] | |
| 49 | + | |
| 50 | +glob-parse 103 "o*test}] | |
| 51 | + | |
| 52 | +glob-parse 101 "one two" one [string map [list \r\n \n] \ | |
| 53 | +*' OR x GLOB 'two') | |
| 54 | +pattern[0] =0 two one}] | |
| 55 | + | |
| 56 | +glob-p04 {"o* two" "three four"} "one two" [string map [list \r\n \n] \ | |
| 57 | +{SQL expression: (x GLOB 'o* two' OR x GLOB 'three four') | |
| 58 | +pattern[0] = [o* two] | |
| 59 | +pone two}] | |
| 60 | + | |
| 61 | +glob-parse 105 {"o* two" "three four"} "5 {"o* two" "three four"} "two one" [string map [list \r\n \n] \ | |
| 62 | +{SQL expression: (x GLOB 'o* two' OR x GLOB 'three four') | |
| 63 | +pattern[0] = [o* two] | |
| 64 | +p] | |
| 65 | +0 0 two one}] | |
| 66 | + | |
| 67 | +glob-p0 0 two one}] | |
| 68 | + | |
| 69 | +glob-parse 106 "\"o*\ntwo\" \"three\nfour\"" "one\ntwo" \ | |
| 70 | +[string map [list \r\n \n] \ | |
| 71 | +{SQL expression: (x GLOB 'o* | |
| 72 | +two' OR x GLOB 'three | |
| 73 | +fou] = [one] | |
| 74 | +pattern[1] = 1 1 one | |
| 75 | +two}] | |
| 76 | + | |
| 77 | +glob-parse 107 "\"o*\ntwo\" \"three\nfour\"" "two\none" \ | |
| 78 | +[string map [list \r\n \n] \ | |
| 79 | +{SQL expression: (x GLOB 'o* | |
| 80 | +two' OR x GLOB 'three | |
| 81 | +foutwo | |
| 82 | +0 two one}] | |
| 83 | + | |
| 84 | +glob-p08 "\"o*\rtwo\" \"three\rfour\"" "one\rtwo" \ | |
| 85 | +[string map [list \r\n \n] \ | |
| 86 | +{SQL expression: (x GLOB 'o* | |
| 87 | +two' OR x GLOB 'three | |
| 88 | +four') | |
| 89 | +pattern[0] = [o* | |
| 90 | +two] | |
| 91 | +p] = [one] | |
| 92 | +pattern[1] = | |
| 93 | + foreach {pattern string result} $args { | |
| 94 | + fossil test-glob $pattern $string | |
| 95 | + test glob-parse-$testname.$i {$::RESULT eq $result} | |
| 96 | + incr i | |
| 97 | + } | |
| 98 | +} | |
| 99 | + | |
| 100 | +gtwo | |
| 101 | +0 two one}] | |
| 102 | + | |
| 103 | +glob-patring map [list \r\n \n] \ | |
| 104 | +{SQL expression: (x GLOB 'test') | |
| 105 | +pattern[0] = [test] | |
| 106 | +1 1 test}] | |
| 107 | + | |
| 108 | +glob-parse 101 "one two" one [string map [list \r\n \n] \ | |
| 109 | +{] = [one] | |
| 110 | +pattern[1] = [two] | |
| 111 | +1 1 one}] | |
| 112 | + | |
| 113 | +glob-parse 102 t* test [string map [list \r\n \n] \ | |
| 114 | +{SQL expression: (x GLOB 't*') | |
| 115 | +pattern[0] = [t*] | |
| 116 | +1 1 test}] | |
| 117 | + | |
| 118 | +glob-parse 103 "o* two" one [st |
| --- a/test/glob.test | |
| +++ b/test/glob.test | |
| @@ -0,0 +1,118 @@ | |
| --- a/test/glob.test | |
| +++ b/test/glob.test | |
| @@ -0,0 +1,118 @@ | |
| 1 | # |
| 2 | # Copyright (c) 2013 D. Richard Hipp |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or |
| 5 | # modify it under the terms of the Simplified BSD License (also |
| 6 | # known as the "2-Clause License" or "FreeBSD License".) |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but without any warranty; without even the implied warranty of |
| 10 | # merchantability or fitness for a particular purpose. |
| 11 | # |
| 12 | # Author contact information: |
| 13 | # [email protected] |
| 14 | # http://www.hwaci.com/drh/ |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # Test glob pattern parsing |
| 19 | # |
| 20 | |
| 21 | parsing |
| 22 | # |
| 23 | |
| 24 | test_setup "" |
| 25 | |
| 26 | proc glob-parse {testname args} { |
| 27 | set i 1 |
| 28 | foreach {pattern string result} $args { |
| 29 | fossil test-glob $pattern $string |
| 30 | test glob-parse-$testname.$i {$::RESULT eq $result} |
| 31 | incr i |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | glob-parse 100 test test [string map [list \r\n \n] \ |
| 36 | {SQL expression: (x GLOB 'test') |
| 37 | pattern[0] = [test] |
| 38 | 1 t*') |
| 39 | pattern[0] = [t*] |
| 40 | 1 1 test}] |
| 41 | |
| 42 | glob-parse 101 "one two" one [string map [list \r\n \n] \ |
| 43 | {SQL expression: (x GLOB 'one' OR x GLOB 'two') |
| 44 | pattern[0] = 0 two one}] |
| 45 | |
| 46 | glob-p02 t* test-parse 108 "\"o*\rtwo\" \"thrt*# |
| 47 | # Copyright (c)# |
| 48 | # 1 test}] |
| 49 | |
| 50 | glob-parse 103 "o*test}] |
| 51 | |
| 52 | glob-parse 101 "one two" one [string map [list \r\n \n] \ |
| 53 | *' OR x GLOB 'two') |
| 54 | pattern[0] =0 two one}] |
| 55 | |
| 56 | glob-p04 {"o* two" "three four"} "one two" [string map [list \r\n \n] \ |
| 57 | {SQL expression: (x GLOB 'o* two' OR x GLOB 'three four') |
| 58 | pattern[0] = [o* two] |
| 59 | pone two}] |
| 60 | |
| 61 | glob-parse 105 {"o* two" "three four"} "5 {"o* two" "three four"} "two one" [string map [list \r\n \n] \ |
| 62 | {SQL expression: (x GLOB 'o* two' OR x GLOB 'three four') |
| 63 | pattern[0] = [o* two] |
| 64 | p] |
| 65 | 0 0 two one}] |
| 66 | |
| 67 | glob-p0 0 two one}] |
| 68 | |
| 69 | glob-parse 106 "\"o*\ntwo\" \"three\nfour\"" "one\ntwo" \ |
| 70 | [string map [list \r\n \n] \ |
| 71 | {SQL expression: (x GLOB 'o* |
| 72 | two' OR x GLOB 'three |
| 73 | fou] = [one] |
| 74 | pattern[1] = 1 1 one |
| 75 | two}] |
| 76 | |
| 77 | glob-parse 107 "\"o*\ntwo\" \"three\nfour\"" "two\none" \ |
| 78 | [string map [list \r\n \n] \ |
| 79 | {SQL expression: (x GLOB 'o* |
| 80 | two' OR x GLOB 'three |
| 81 | foutwo |
| 82 | 0 two one}] |
| 83 | |
| 84 | glob-p08 "\"o*\rtwo\" \"three\rfour\"" "one\rtwo" \ |
| 85 | [string map [list \r\n \n] \ |
| 86 | {SQL expression: (x GLOB 'o* |
| 87 | two' OR x GLOB 'three |
| 88 | four') |
| 89 | pattern[0] = [o* |
| 90 | two] |
| 91 | p] = [one] |
| 92 | pattern[1] = |
| 93 | foreach {pattern string result} $args { |
| 94 | fossil test-glob $pattern $string |
| 95 | test glob-parse-$testname.$i {$::RESULT eq $result} |
| 96 | incr i |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | gtwo |
| 101 | 0 two one}] |
| 102 | |
| 103 | glob-patring map [list \r\n \n] \ |
| 104 | {SQL expression: (x GLOB 'test') |
| 105 | pattern[0] = [test] |
| 106 | 1 1 test}] |
| 107 | |
| 108 | glob-parse 101 "one two" one [string map [list \r\n \n] \ |
| 109 | {] = [one] |
| 110 | pattern[1] = [two] |
| 111 | 1 1 one}] |
| 112 | |
| 113 | glob-parse 102 t* test [string map [list \r\n \n] \ |
| 114 | {SQL expression: (x GLOB 't*') |
| 115 | pattern[0] = [t*] |
| 116 | 1 1 test}] |
| 117 | |
| 118 | glob-parse 103 "o* two" one [st |