X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fglobmatch.c;fp=src%2Fglobmatch.c;h=4cb1f0014ca89cd36438d1df02725c68097d1be5;hb=caea0053d2abc141ab585324fb51f8c536db249b;hp=0000000000000000000000000000000000000000;hpb=64ca02ceed8acd4b55e423de6b586a143f5a3c64;p=src%2Fapp-framework-binder.git diff --git a/src/globmatch.c b/src/globmatch.c new file mode 100644 index 00000000..4cb1f001 --- /dev/null +++ b/src/globmatch.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2018, 2019 "IoT.bzh" + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE + +#include + +#include "globmatch.h" + +/** + * Matches whether the string 'str' matches the pattern 'pat' + * and returns its matching score. + * + * @param pat the glob pattern + * @param str the string to match + * @return 0 if no match or number representing the matching score + */ +static unsigned match(const char *pat, const char *str, int flags) +{ + unsigned r, rs, rr; + char c, x; + int eq; + + /* scan the prefix without glob */ + r = 1; + while ((c = *pat++) != GLOB) { + x = *str++; + eq = (flags & FNM_CASEFOLD) ? (tolower(c) == tolower(x)) : (c == x); + if (!eq) + return 0; /* no match */ + if (!c) + return r; /* match up to end */ + r++; + } + + /* glob found */ + c = *pat++; + if (!c) { + /* not followed by pattern */ + if (flags & FNM_PATHNAME) { + while(*str) + if (*str++ == '/') + return 0; + } + return r; + } + + /* evaluate the best score for following pattern */ + rs = 0; + while (*str) { + x = *str++; + eq = (flags & FNM_CASEFOLD) ? (tolower(c) == tolower(x)) : (c == x); + if (eq) { + /* first char matches, check remaining string */ + rr = match(pat, str, flags); + if (rr > rs) + rs = rr; + } else if ((flags & FNM_PATHNAME) && x == '/') + return 0; + } + + /* best score or not match if rs == 0 */ + return rs ? rs + r : 0; +} + +/** + * Matches whether the string 'str' matches the pattern 'pat' + * and returns its matching score. + * + * @param pat the glob pattern + * @param str the string to match + * @return 0 if no match or number representing the matching score + */ +unsigned globmatch(const char *pat, const char *str) +{ + return match(pat, str, 0); +} + +/** + * Matches whether the string 'str' matches the pattern 'pat' + * and returns its matching score. + * + * @param pat the glob pattern + * @param str the string to match + * @return 0 if no match or number representing the matching score + */ +unsigned globmatchi(const char *pat, const char *str) +{ + return match(pat, str, FNM_CASEFOLD); +} + +#if !WITH_FNMATCH +int fnmatch(const char *pattern, const char *string, int flags) +{ + return !match(pattern, string, flags); +} +#endif