void testFileSystem() { printf("FileSystem..."); debugAssert(g3dfnmatch("*.zip", "hello.not", FNM_PERIOD | FNM_NOESCAPE | FNM_PATHNAME) == FNM_NOMATCH); debugAssert(g3dfnmatch("*.zip", "hello.zip", FNM_PERIOD | FNM_NOESCAPE | FNM_PATHNAME) == 0); debugAssert(FilePath::matches("hello", "*", false)); debugAssert(FilePath::matches("hello", "*", true)); chdir("TestDir"); std::string cwd = FileSystem::currentDirectory(); debugAssert(endsWith(cwd, "TestDir")); chdir(".."); // Directory listing Array<std::string> files; FileSystem::getFiles("*", files); debugAssert(files.contains("Any-load.txt")); debugAssert(files.contains("apiTest.zip")); // Directory listing files.clear(); FileSystem::getFiles("*.zip", files); debugAssert(files.contains("apiTest.zip")); debugAssert(files.size() == 1); // Directory listing inside zipfile files.clear(); debugAssert(FileSystem::exists("apiTest.zip")); debugAssert(FileSystem::isZipfile("apiTest.zip")); FileSystem::getFiles("apiTest.zip/*", files); debugAssert(files.size() == 1); debugAssert(files.contains("Test.txt")); files.clear(); FileSystem::getDirectories("apiTest.zip/*", files); debugAssert(files.size() == 1); debugAssert(files.contains("zipTest")); debugAssert(! FileSystem::exists("nothere")); debugAssert(FileSystem::exists("apiTest.zip/Test.txt")); debugAssert(! FileSystem::exists("apiTest.zip/no.txt")); debugAssert(FileSystem::size("apiTest.zip") == 488); printf("passed\n"); }
int g3dfnmatch(const char *pattern, const char *string, int flags) { const char *stringstart; char *newp; char c, test; for (stringstart = string;;) switch (c = *pattern++) { case EOS: if ((flags & FNM_LEADING_DIR) && *string == '/') return (0); return (*string == EOS ? 0 : FNM_NOMATCH); case '?': if (*string == EOS) return (FNM_NOMATCH); if (*string == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); ++string; break; case '*': c = *pattern; /* Collapse multiple stars. */ while (c == '*') c = *++pattern; if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); /* Optimize for pattern with * at end or before /. */ if (c == EOS) { if (flags & FNM_PATHNAME) return ((flags & FNM_LEADING_DIR) || strchr(string, '/') == NULL ? 0 : FNM_NOMATCH); else return (0); } else if (c == '/' && (flags & FNM_PATHNAME)) { if ((string = strchr(string, '/')) == NULL) return (FNM_NOMATCH); break; } /* General case, use recursion. */ while ((test = *string) != EOS) { if (!g3dfnmatch(pattern, string, flags & ~FNM_PERIOD)) return (0); if (test == '/' && (flags & FNM_PATHNAME)) break; ++string; } return (FNM_NOMATCH); case '[': if (*string == EOS) return (FNM_NOMATCH); if (*string == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); switch (rangematch(pattern, *string, flags, &newp)) { case RANGE_ERROR: /* not a good range, treat as normal text */ goto normal; case RANGE_MATCH: pattern = newp; break; case RANGE_NOMATCH: return (FNM_NOMATCH); } ++string; break; case '\\': if (!(flags & FNM_NOESCAPE)) { if ((c = *pattern++) == EOS) { c = '\\'; --pattern; } } /* FALLTHROUGH */ default: normal: if (c != *string && !((flags & FNM_CASEFOLD) && (tolower((unsigned char)c) == tolower((unsigned char)*string)))) return (FNM_NOMATCH); ++string; break; } /* NOTREACHED */ }