diff --git a/libretrodb/Makefile b/libretrodb/Makefile index df66a51e95..b4fc4247b3 100644 --- a/libretrodb/Makefile +++ b/libretrodb/Makefile @@ -8,7 +8,7 @@ LUA_CONVERTER_OBJ = rmsgpack.o \ bintree.o \ query.o \ lua_converter.o \ - rl_fnmatch.c \ + compat_fnmatch.c \ $(NULL) RARCHDB_TOOL_OBJ = rmsgpack.o \ @@ -17,13 +17,13 @@ RARCHDB_TOOL_OBJ = rmsgpack.o \ bintree.o \ query.o \ rarchdb.o \ - rl_fnmatch.c \ + compat_fnmatch.c \ $(NULL) TESTLIB_C = testlib.c \ lua_common.c \ query.c \ - rl_fnmatch.c \ + compat_fnmatch.c \ rarchdb.c \ bintree.c \ rmsgpack.c \ diff --git a/libretrodb/compat_fnmatch.c b/libretrodb/compat_fnmatch.c new file mode 100644 index 0000000000..5d409a3da4 --- /dev/null +++ b/libretrodb/compat_fnmatch.c @@ -0,0 +1,157 @@ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (compat_fnmatch.c). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if __TEST_FNMATCH__ +#include +#endif + +#include + +/* Implemnentation of fnmatch(3) so it can be + * distributed to non *nix platforms. + * + * No flags are implemented ATM. + * We don't use them. Add flags as needed. */ + +int rl_fnmatch(const char *pattern, const char *string, int flags) +{ + const char *c; + int charmatch = 0; + int rv; + for (c = pattern; *c != '\0'; c++) + { + /* String ended before pattern */ + if ((*c != '*') && (*string == '\0')) + return FNM_NOMATCH; + + switch (*c) + { + /* Match any number of unknown chars */ + case '*': + /* Find next node in the pattern + * ignoring multiple asterixes + */ + do { + c++; + if (*c == '\0') + return 0; + } while (*c == '*'); + + /* Match the remaining pattern + * ignoring more and more characters. */ + do { + /* We reached the end of the string without a + * match. There is a way to optimize this by + * calculating the minimum chars needed to + * match the remaining pattern but I don't + * think it is worth the work ATM. + */ + if (*string == '\0') + return FNM_NOMATCH; + + rv = rl_fnmatch(c, string, flags); + string++; + } while (rv != 0); + + return 0; + /* Match char from list */ + case '[': + charmatch = 0; + for (c++; *c != ']'; c++) + { + /* Bad format */ + if (*c == '\0') + return FNM_NOMATCH; + + /* Match already found */ + if (charmatch) + continue; + + if (*c == *string) + charmatch = 1; + } + + /* No match in list */ + if (!charmatch) + return FNM_NOMATCH; + + string++; + break; + /* Has any character */ + case '?': + string++; + break; + /* Match following character verbatim */ + case '\\': + c++; + /* Dangling escape at end of pattern. + * FIXME: Was c == '\0' (makes no sense). + * Not sure if c == NULL or *c == '\0' + * is intended. Assuming *c due to c++ right before. */ + if (*c == '\0') + return FNM_NOMATCH; + default: + if (*c != *string) + return FNM_NOMATCH; + string++; + } + } + + /* End of string and end of pattend */ + if (*string == '\0') + return 0; + return FNM_NOMATCH; +} + +#if __TEST_FNMATCH__ +int main(void) +{ + assert(rl_fnmatch("TEST", "TEST", 0) == 0); + assert(rl_fnmatch("TE?T", "TEST", 0) == 0); + assert(rl_fnmatch("TE[Ssa]T", "TEST", 0) == 0); + assert(rl_fnmatch("TE[Ssda]T", "TEsT", 0) == 0); + assert(rl_fnmatch("TE[Ssda]T", "TEdT", 0) == 0); + assert(rl_fnmatch("TE[Ssda]T", "TEaT", 0) == 0); + assert(rl_fnmatch("TEST*", "TEST", 0) == 0); + assert(rl_fnmatch("TEST**", "TEST", 0) == 0); + assert(rl_fnmatch("TE*ST*", "TEST", 0) == 0); + assert(rl_fnmatch("TE**ST*", "TEST", 0) == 0); + assert(rl_fnmatch("TE**ST*", "TExST", 0) == 0); + assert(rl_fnmatch("TE**ST", "TEST", 0) == 0); + assert(rl_fnmatch("TE**ST", "TExST", 0) == 0); + assert(rl_fnmatch("TE\\**ST", "TE*xST", 0) == 0); + assert(rl_fnmatch("*.*", "test.jpg", 0) == 0); + assert(rl_fnmatch("*.jpg", "test.jpg", 0) == 0); + assert(rl_fnmatch("*.[Jj][Pp][Gg]", "test.jPg", 0) == 0); + assert(rl_fnmatch("*.[Jj]*[Gg]", "test.jPg", 0) == 0); + assert(rl_fnmatch("TEST?", "TEST", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TES[asd", "TEST", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TEST\\", "TEST", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TEST*S", "TEST", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TE**ST", "TExT", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TE\\*T", "TExT", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TES?", "TES", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TE", "TEST", 0) == FNM_NOMATCH); + assert(rl_fnmatch("TEST!", "TEST", 0) == FNM_NOMATCH); + assert(rl_fnmatch("DSAD", "TEST", 0) == FNM_NOMATCH); +} +#endif diff --git a/libretrodb/fnmatch.h b/libretrodb/fnmatch.h new file mode 100644 index 0000000000..99a6ae9b4a --- /dev/null +++ b/libretrodb/fnmatch.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (compat_fnmatch.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_COMPAT_FNMATCH_H__ +#define __LIBRETRO_SDK_COMPAT_FNMATCH_H__ + +#define FNM_NOMATCH 1 + +int rl_fnmatch(const char *pattern, const char *string, int flags); + +#endif