forked from Kenix3/libultraship
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements a new Glob matching function. (Kenix3#518)
* Implements a new Glob matching function. * clang-format * Correctly cite the glob.c file * Correctly cite the glob.c file
- Loading branch information
Showing
7 changed files
with
141 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#include "glob.h" | ||
#include <stddef.h> | ||
|
||
// This has been borrowed from the dual MIT/GPL licensed glob module from the Linux kernel under the MIT license. | ||
// See https://github.com/torvalds/linux/blob/d1bd5fa07667fcc3e38996ec42aef98761f23039/lib/glob.c | ||
|
||
/** | ||
* glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) | ||
* @pat: Shell-style pattern to match, e.g. "*.[ch]". | ||
* @str: String to match. The pattern must match the entire string. | ||
* | ||
* Perform shell-style glob matching, returning true (1) if the match | ||
* succeeds, or false (0) if it fails. Equivalent to !fnmatch(@pat, @str, 0). | ||
* | ||
* Pattern metacharacters are ?, *, [ and \. | ||
* (And, inside character classes, !, - and ].) | ||
* | ||
* This is small and simple implementation intended for device blacklists | ||
* where a string is matched against a number of patterns. Thus, it | ||
* does not preprocess the patterns. It is non-recursive, and run-time | ||
* is at most quadratic: strlen(@str)*strlen(@pat). | ||
* | ||
* An example of the worst case is glob_match("*aaaaa", "aaaaaaaaaa"); | ||
* it takes 6 passes over the pattern before matching the string. | ||
* | ||
* Like !fnmatch(@pat, @str, 0) and unlike the shell, this does NOT | ||
* treat / or leading . specially; it isn't actually used for pathnames. | ||
* | ||
* Note that according to glob(7) (and unlike bash), character classes | ||
* are complemented by a leading !; this does not support the regex-style | ||
* [^a-z] syntax. | ||
* | ||
* An opening bracket without a matching close is matched literally. | ||
*/ | ||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
bool glob_match(char const* pat, char const* str) { | ||
/* | ||
* Backtrack to previous * on mismatch and retry starting one | ||
* character later in the string. Because * matches all characters | ||
* (no exception for /), it can be easily proved that there's | ||
* never a need to backtrack multiple levels. | ||
*/ | ||
char const *back_pat = NULL, *back_str = NULL; | ||
|
||
/* | ||
* Loop over each token (character or class) in pat, matching | ||
* it against the remaining unmatched tail of str. Return false | ||
* on mismatch, or true after matching the trailing nul bytes. | ||
*/ | ||
for (;;) { | ||
unsigned char c = *str++; | ||
unsigned char d = *pat++; | ||
|
||
switch (d) { | ||
case '?': /* Wildcard: anything but nul */ | ||
if (c == '\0') | ||
return false; | ||
break; | ||
case '*': /* Any-length wildcard */ | ||
if (*pat == '\0') /* Optimize trailing * case */ | ||
return true; | ||
back_pat = pat; | ||
back_str = --str; /* Allow zero-length match */ | ||
break; | ||
case '[': { /* Character class */ | ||
bool match = false, inverted = (*pat == '!'); | ||
char const* class = pat + inverted; | ||
unsigned char a = *class ++; | ||
|
||
/* | ||
* Iterate over each span in the character class. | ||
* A span is either a single character a, or a | ||
* range a-b. The first span may begin with ']'. | ||
*/ | ||
do { | ||
unsigned char b = a; | ||
|
||
if (a == '\0') /* Malformed */ | ||
goto literal; | ||
|
||
if (class[0] == '-' && class[1] != ']') { | ||
b = class[1]; | ||
|
||
if (b == '\0') | ||
goto literal; | ||
|
||
class += 2; | ||
/* Any special action if a > b? */ | ||
} | ||
match |= (a <= c && c <= b); | ||
} while ((a = *class ++) != ']'); | ||
|
||
if (match == inverted) | ||
goto backtrack; | ||
pat = class; | ||
} break; | ||
case '\\': | ||
d = *pat++; | ||
//fallthrough; | ||
default: /* Literal character */ | ||
literal: | ||
if (c == d) { | ||
if (d == '\0') | ||
return true; | ||
break; | ||
} | ||
backtrack: | ||
if (c == '\0' || !back_pat) | ||
return false; /* No point continuing */ | ||
/* Try again from last *, one character later in str. */ | ||
pat = back_pat; | ||
str = ++back_str; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
#ifdef __cplusplus | ||
} | ||
; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
#include <stdbool.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
bool glob_match(char const* pat, char const* str); | ||
#ifdef __cplusplus | ||
}; | ||
#endif |