diff options
Diffstat (limited to 'dep/src/g3dlite/fileutils.cpp')
-rw-r--r-- | dep/src/g3dlite/fileutils.cpp | 1165 |
1 files changed, 0 insertions, 1165 deletions
diff --git a/dep/src/g3dlite/fileutils.cpp b/dep/src/g3dlite/fileutils.cpp deleted file mode 100644 index 3f5eb579ba9..00000000000 --- a/dep/src/g3dlite/fileutils.cpp +++ /dev/null @@ -1,1165 +0,0 @@ -/** - @file fileutils.cpp - - @author Morgan McGuire, graphics3d.com - - @author 2002-06-06 - @edited 2010-02-05 - */ - -#include <cstring> -#include <cstdio> -#include "G3D/platform.h" -#include "G3D/fileutils.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/g3dmath.h" -#include "G3D/stringutils.h" -#include "G3D/Set.h" -#include "G3D/g3dfnmatch.h" - -#include <sys/stat.h> -#include <sys/types.h> -#if _HAVE_ZIP - #include "zip.h" -#endif - -#ifdef G3D_WIN32 - // Needed for _getcwd - #include <direct.h> - #include <io.h> -#else - #include <dirent.h> - #include <fnmatch.h> - #include <unistd.h> - #define _getcwd getcwd - #define _stat stat -#endif - - -namespace G3D { - -namespace _internal { - Set<std::string> currentFilesUsed; -} - -std::string pathConcat(const std::string& dirname, const std::string& file) { - // Ensure that the directory ends in a slash - if ((dirname.size() != 0) && - (dirname[dirname.size() - 1] != '/') && - (dirname[dirname.size() - 1] != '\\') && - (dirname[dirname.size() - 1] != ':')) { - return dirname + '/' + file; - } else { - return dirname + file; - } -} - -std::string resolveFilename(const std::string& filename) { - if (filename.size() >= 1) { - if ((filename[0] == '/') || (filename[0] == '\\')) { - // Already resolved - return filename; - } else { - - #ifdef G3D_WIN32 - if ((filename.size() >= 2) && (filename[1] == ':')) { - // There is a drive spec on the front. - if ((filename.size() >= 3) && ((filename[2] == '\\') || - (filename[2] == '/'))) { - // Already fully qualified - return filename; - } else { - // The drive spec is relative to the - // working directory on that drive. - debugAssertM(false, "Files of the form d:path are" - " not supported (use a fully qualified" - " name)."); - return filename; - } - } - #endif - } - } - - char buffer[1024]; - - // Prepend the working directory. - _getcwd(buffer, 1024); - - return format("%s/%s", buffer, filename.c_str()); -} - -bool zipfileExists(const std::string& filename) { - std::string outZipfile; - std::string outInternalFile; - return zipfileExists(filename, outZipfile, outInternalFile); -} - -std::string readWholeFile( - const std::string& filename) { - - _internal::currentFilesUsed.insert(filename); - - std::string s; - - debugAssert(filename != ""); - if (fileExists(filename, false)) { - - int64 length = fileLength(filename); - - char* buffer = (char*)System::alignedMalloc(length + 1, 16); - debugAssert(buffer); - FILE* f = fopen(filename.c_str(), "rb"); - debugAssert(f); - int ret = fread(buffer, 1, length, f); - debugAssert(ret == length);(void)ret; - fclose(f); - - buffer[length] = '\0'; - s = std::string(buffer); - - System::alignedFree(buffer); - - } else if (zipfileExists(filename)) { - - void* zipBuffer; - size_t length; - zipRead(filename, zipBuffer, length); - - char* buffer = (char*)System::alignedMalloc(length + 1, 16); - System::memcpy(buffer,zipBuffer, length + 1); - zipClose(zipBuffer); - - buffer[length] = '\0'; - s = std::string(buffer); - System::alignedFree(buffer); - } else { - debugAssertM(false, filename + " not found"); - } - - return s; -} - - -void zipRead(const std::string& file, - void*& data, - size_t& length) { - std::string zip, desiredFile; -#if _HAVE_ZIP - if (zipfileExists(file, zip, desiredFile)) { - struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL ); - { - struct zip_stat info; - zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required. - zip_stat( z, desiredFile.c_str(), ZIP_FL_NOCASE, &info ); - length = info.size; - // sets machines up to use MMX, if they want - data = System::alignedMalloc(length, 16); - struct zip_file *zf = zip_fopen( z, desiredFile.c_str(), ZIP_FL_NOCASE ); - { - int test = zip_fread( zf, data, length ); - debugAssertM((size_t)test == length, - desiredFile + " was corrupt because it unzipped to the wrong size."); - (void)test; - } - zip_fclose( zf ); - } - zip_close( z ); - } else { - data = NULL; - } -#else - data = NULL; -#endif -} - - -void zipClose(void* data) { - System::alignedFree(data); -} - - -int64 fileLength(const std::string& filename) { - struct _stat st; - int result = _stat(filename.c_str(), &st); - - if (result == -1) { -#if _HAVE_ZIP - std::string zip, contents; - if(zipfileExists(filename, zip, contents)){ - int64 requiredMem; - - struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL ); - debugAssertM(z != NULL, zip + ": zip open failed."); - { - struct zip_stat info; - zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required. - int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info ); - debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed."); - requiredMem = info.size; - } - zip_close( z ); - return requiredMem; - } else { - return -1; - } -#else - return -1; -#endif - } - - return st.st_size; -} - -/** Used by robustTmpfile. Returns nonzero if fread, fwrite, and fseek all -succeed on the file. - @author Morgan McGuire, http://graphics.cs.williams.edu */ -static int isFileGood(FILE* f) { - - int x, n, result; - - /* Must be a valid file handle */ - if (f == NULL) { - return 0; - } - - /* Try to write */ - x = 1234; - n = fwrite(&x, sizeof(int), 1, f); - - if (n != 1) { - return 0; - } - - /* Seek back to the beginning */ - result = fseek(f, 0, SEEK_SET); - if (result != 0) { - return 0; - } - - /* Read */ - n = fread(&x, sizeof(int), 1, f); - if (n != 1) { - return 0; - } - - /* Seek back to the beginning again */ - fseek(f, 0, SEEK_SET); - - return 1; -} - -FILE* createTempFile() { - FILE* t = NULL; - -//# ifdef G3D_WIN32 - t = tmpfile(); -//# else -// // On Unix, tmpfile generates a warning for any code that links against it. -// const char* tempfilename = "/tmp/g3dtemp.XXXXXXXX"; -// mktemp(tempfilename); -// t = fopen(tempfilename, "w"); -//# endif - -# ifdef _WIN32 - char* n = NULL; -# endif - char name[256]; - - if (isFileGood(t)) { - return t; - } - -# ifdef G3D_WIN32 - /* tmpfile failed; try the tmpnam routine */ - t = fopen(tmpnam(NULL), "w+"); - if (isFileGood(t)) { - return t; - } - - n = _tempnam("c:/tmp/", "t"); - /* Try to create something in C:\tmp */ - t = fopen(n, "w+"); - if (isFileGood(t)) { - return t; - } - - /* Try c:\temp */ - n = _tempnam("c:/temp/", "t"); - t = fopen(n, "w+"); - if (isFileGood(t)) { - return t; - } - - /* try the current directory */ - n = _tempnam("./", "t"); - t = fopen(n, "w+"); - if (isFileGood(t)) { - return t; - } - - sprintf(name, "%s/tmp%d", "c:/temp", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } - - /* Try some hardcoded paths */ - sprintf(name, "%s/tmp%d", "c:/tmp", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } -# else - sprintf(name, "%s/tmp%d", "/tmp", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } -#endif - - sprintf(name, "tmp%d", rand()); - t = fopen(name, "w+"); - if (isFileGood(t)) { - return t; - } - - fprintf(stderr, "Unable to create a temporary file; robustTmpfile returning NULL\n"); - - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// -void writeWholeFile( - const std::string& filename, - const std::string& str, - bool flush) { - - // Make sure the directory exists. - std::string root, base, ext, path; - Array<std::string> pathArray; - parseFilename(filename, root, pathArray, base, ext); - - path = root + stringJoin(pathArray, '/'); - if (! fileExists(path, false)) { - createDirectory(path); - } - - FILE* file = fopen(filename.c_str(), "wb"); - - debugAssert(file); - - fwrite(str.c_str(), str.size(), 1, file); - - if (flush) { - fflush(file); - } - fclose(file); -} - -/////////////////////////////////////////////////////////////////////////////// - -/** - Creates the directory (which may optionally end in a /) - and any parents needed to reach it. - */ -void createDirectory( - const std::string& dir) { - - if (dir == "") { - return; - } - - std::string d; - - // Add a trailing / if there isn't one. - switch (dir[dir.size() - 1]) { - case '/': - case '\\': - d = dir; - break; - - default: - d = dir + "/"; - } - - // If it already exists, do nothing - if (fileExists(d.substr(0, d.size() - 1)), false) { - return; - } - - // Parse the name apart - std::string root, base, ext; - Array<std::string> path; - - std::string lead; - parseFilename(d, root, path, base, ext); - debugAssert(base == ""); - debugAssert(ext == ""); - - // Begin with an extra period so "c:\" becomes "c:\.\" after - // appending a path and "c:" becomes "c:.\", not root: "c:\" - std::string p = root + "."; - - // Create any intermediate that doesn't exist - for (int i = 0; i < path.size(); ++i) { - p += "/" + path[i]; - if (! fileExists(p, false)) { - // Windows only requires one argument to mkdir, - // where as unix also requires the permissions. -# ifndef G3D_WIN32 - mkdir(p.c_str(), 0777); -# else - _mkdir(p.c_str()); -# endif - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -class FileSystemCache { -private: - - Table<std::string, Array<std::string> > m_files; - -public: - - bool fileExists(const std::string& filename) { - const std::string& path = resolveFilename(filenamePath(filename)); - const std::string& name = filenameBaseExt(filename); - - bool neverBeforeSeen = false; - Array<std::string>& fileList = m_files.getCreate(path, neverBeforeSeen); - if (neverBeforeSeen) { - if (! G3D::fileExists(path, true, false)) { - // The path itself doesn't exist... back out our insertion (which makes fileList& invalid) - m_files.remove(path); - return false; - } - - std::string spec = pathConcat(path, "*"); - - // Will automatically recurse into zipfiles - getFiles(spec, fileList); - getDirs(spec, fileList); - -# ifdef G3D_WIN32 - { - // Case insensitive - for (int i = 0; i < fileList.size(); ++i) { - fileList[i] = toLower(fileList[i]); - } - } -# endif - } - - if (filenameContainsWildcards(name)) { - // See if anything matches - for (int i = 0; i < fileList.size(); ++i) { - if (g3dfnmatch(name.c_str(), fileList[i].c_str(), 0) == 0) { - return true; - } - } - return false; - } else { - // On windows, this is a lower-lower comparison, so it is case insensitive - return fileList.contains(name); - } - } - - void clear() { - m_files.clear(); - } - - static FileSystemCache& instance() { - static FileSystemCache i; - return i; - } -}; - - -void clearFileSystemCache() { - FileSystemCache::instance().clear(); -} - -bool fileExists -(const std::string& _filename, - bool lookInZipfiles, - bool trustCache) { - - if (_filename.empty()) { - return false; - } - - // Remove trailing slash from directories - const std::string& filename = (endsWith(_filename, "/") || endsWith(_filename, "\\")) ? _filename.substr(0, _filename.length() - 1) : _filename; - - if (trustCache && lookInZipfiles) { -# ifdef G3D_WIN32 - // Case insensitive - return FileSystemCache::instance().fileExists(toLower(filename)); -# else - return FileSystemCache::instance().fileExists(filename); -# endif - } - - // Useful for debugging - //char curdir[1024]; _getcwd(curdir, 1024); - - struct _stat st; - int ret = _stat(filename.c_str(), &st); - - // _stat returns zero on success - bool exists = (ret == 0); - - if (! exists && lookInZipfiles) { - // Does not exist standalone, but might exist in a zipfile - - // These output arguments will be ignored - std::string zipDir, internalPath; - return zipfileExists(filename, zipDir, internalPath); - } else { - return exists; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -#if _HAVE_ZIP -/* Helper methods for zipfileExists()*/ -// Given a string (the drive) and an array (the path), computes the directory -static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){ - completeDir = drive; - int tempLength; - // if the given length is longer than the array, we correct it - if(length > path.length()){ - tempLength = path.length(); - } else{ - tempLength = length; - } - - for(int t = 0; t < tempLength; ++t){ - if(t > 0){ - completeDir += "/"; - } - completeDir += path[t]; - } -} - - -// assumes that zipDir references a .zip file -static bool _zip_zipContains(const std::string& zipDir, const std::string& desiredFile){ - struct zip *z = zip_open( zipDir.c_str(), ZIP_CHECKCONS, NULL ); - //the last parameter, an int, determines case sensitivity: - //1 is sensitive, 2 is not, 0 is default - int test = zip_name_locate( z, desiredFile.c_str(), ZIP_FL_NOCASE ); - zip_close( z ); - if(test == -1){ - return false; - } - return true; -} -#endif - -// If no zipfile exists, outZipfile and outInternalFile are unchanged -bool zipfileExists(const std::string& filename, std::string& outZipfile, - std::string& outInternalFile){ -#if _HAVE_ZIP - Array<std::string> path; - std::string drive, base, ext, zipfile, infile; - parseFilename(filename, drive, path, base, ext); - - // Put the filename back together - if ((base != "") && (ext != "")) { - infile = base + "." + ext; - } else { - infile = base + ext; - } - - // Remove "." from path - for (int i = 0; i < path.length(); ++i) { - if (path[i] == ".") { - path.remove(i); - --i; - } - } - - // Remove ".." from path - for (int i = 1; i < path.length(); ++i) { - if ((path[i] == "..") && (i > 0) && (path[i - 1] != "..")) { - // Remove both i and i - 1 - path.remove(i - 1, 2); - i -= 2; - } - } - - // Walk the path backwards, accumulating pieces onto the infile until - // we find a zipfile that contains it - for (int t = 0; t < path.length(); ++t){ - _zip_resolveDirectory(zipfile, drive, path, path.length() - t); - if (t > 0) { - infile = path[path.length() - t] + "/" + infile; - } - - if (endsWith(zipfile, "..")) { - return false; - } - - if (fileExists(zipfile, false)) { - // test if it actually is a zipfile - // if not, return false, a bad - // directory structure has been given, - // not a .zip - if (isZipfile(zipfile)){ - - if (_zip_zipContains(zipfile, infile)){ - outZipfile = zipfile; - outInternalFile = infile; - return true; - } else { - return false; - } - } else { - // the directory structure was valid but did not point to a .zip - return false; - } - } - - } -#endif - // not a valid directory structure ever, - // obviously no .zip was found within the path - return false; -} - -/////////////////////////////////////////////////////////////////////////////// - -std::string generateFilenameBase(const std::string& prefix, const std::string& suffix) { - Array<std::string> exist; - - // Note "template" is a reserved word in C++ - std::string templat = prefix + System::currentDateString() + "_"; - getFiles(templat + "*", exist); - - // Remove extensions - for (int i = 0; i < exist.size(); ++i) { - exist[i] = filenameBase(exist[i]); - } - - int num = 0; - std::string result; - templat += "%03d" + suffix; - do { - result = format(templat.c_str(), num); - ++num; - } while (exist.contains(result)); - - return result; -} - -/////////////////////////////////////////////////////////////////////////////// - -void copyFile( - const std::string& source, - const std::string& dest) { - - #ifdef G3D_WIN32 - CopyFileA(source.c_str(), dest.c_str(), FALSE); - #else - // TODO: don't use BinaryInput and BinaryOutput - // Read it all in, then dump it out - BinaryInput in(source, G3D_LITTLE_ENDIAN); - BinaryOutput out(dest, G3D_LITTLE_ENDIAN); - out.writeBytes(in.getCArray(), in.size()); - out.commit(false); - #endif -} - -////////////////////////////////////////////////////////////////////////////// - -void parseFilename( - const std::string& filename, - std::string& root, - Array<std::string>& path, - std::string& base, - std::string& ext) { - - std::string f = filename; - - root = ""; - path.clear(); - base = ""; - ext = ""; - - if (f == "") { - // Empty filename - return; - } - - // See if there is a root/drive spec. - if ((f.size() >= 2) && (f[1] == ':')) { - - if ((f.size() > 2) && isSlash(f[2])) { - - // e.g. c:\foo - root = f.substr(0, 3); - f = f.substr(3, f.size() - 3); - - } else { - - // e.g. c:foo - root = f.substr(2); - f = f.substr(2, f.size() - 2); - - } - - } else if ((f.size() >= 2) & isSlash(f[0]) && isSlash(f[1])) { - - // e.g. //foo - root = f.substr(0, 2); - f = f.substr(2, f.size() - 2); - - } else if (isSlash(f[0])) { - - root = f.substr(0, 1); - f = f.substr(1, f.size() - 1); - - } - - // Pull the extension off - { - // Find the period - size_t i = f.rfind('.'); - - if (i != std::string::npos) { - // Make sure it is after the last slash! - size_t j = iMax(f.rfind('/'), f.rfind('\\')); - if ((j == std::string::npos) || (i > j)) { - ext = f.substr(i + 1, f.size() - i - 1); - f = f.substr(0, i); - } - } - } - - // Pull the basename off - { - // Find the last slash - size_t i = iMax(f.rfind('/'), f.rfind('\\')); - - if (i == std::string::npos) { - - // There is no slash; the basename is the whole thing - base = f; - f = ""; - - } else if ((i != std::string::npos) && (i < f.size() - 1)) { - - base = f.substr(i + 1, f.size() - i - 1); - f = f.substr(0, i); - - } - } - - // Parse what remains into path. - size_t prev, cur = 0; - - while (cur < f.size()) { - prev = cur; - - // Allow either slash - size_t i = f.find('/', prev + 1); - size_t j = f.find('\\', prev + 1); - if (i == std::string::npos) { - i = f.size(); - } - - if (j == std::string::npos) { - j = f.size(); - } - - cur = iMin(i, j); - - if (cur == std::string::npos) { - cur = f.size(); - } - - path.append(f.substr(prev, cur - prev)); - ++cur; - } -} - - -/** - Helper for getFileList and getDirectoryList. - - @param wantFiles If false, returns the directories, otherwise - returns the files. - @param includePath If true, the names include paths - */ -static void getFileOrDirListNormal -(const std::string& filespec, - Array<std::string>& files, - bool wantFiles, - bool includePath) { - - bool test = wantFiles ? true : false; - - std::string path = ""; - - // Find the place where the path ends and the file-spec begins - size_t i = filespec.rfind('/'); - size_t j = filespec.rfind('\\'); - - // Drive letters on Windows can separate a path - size_t k = filespec.rfind(':'); - - if (((j != std::string::npos) && (j > i)) || - (i == std::string::npos)) { - i = j; - } - - if (((k != std::string::npos) && (k > i)) || - (i == std::string::npos)) { - i = k; - } - - // If there is a path, pull it off - if (i != std::string::npos) { - path = filespec.substr(0, i + 1); - } - - std::string prefix = path; - - if (path.size() > 0) { - // Strip the trailing character - path = path.substr(0, path.size() - 1); - } - -# ifdef G3D_WIN32 - { - struct _finddata_t fileinfo; - - long handle = _findfirst(filespec.c_str(), &fileinfo); - int result = handle; - - while (result != -1) { - if ((((fileinfo.attrib & _A_SUBDIR) == 0) == test) && - strcmp(fileinfo.name, ".") && - strcmp(fileinfo.name, "..")) { - - if (includePath) { - files.append(prefix + fileinfo.name); - } else { - files.append(fileinfo.name); - } - } - - result = _findnext(handle, &fileinfo); - } - } -# else - { - if (path == "") { - // Empty paths don't work on Unix - path = "."; - } - - // Unix implementation - DIR* dir = opendir(path.c_str()); - - if (dir != NULL) { - struct dirent* entry = readdir(dir); - - while (entry != NULL) { - - // Exclude '.' and '..' - if ((strcmp(entry->d_name, ".") != 0) && - (strcmp(entry->d_name, "..") != 0)) { - - // Form a name with a path - std::string filename = prefix + entry->d_name; - // See if this is a file or a directory - struct _stat st; - bool exists = _stat(filename.c_str(), &st) != -1; - - if (exists && - - // Make sure it has the correct type - (((st.st_mode & S_IFDIR) == 0) == test) && - - // Make sure it matches the wildcard - (fnmatch(filespec.c_str(), - filename.c_str(), - FNM_PATHNAME) == 0)) { - - if (includePath) { - files.append(filename); - } else { - files.append(entry->d_name); - } - } - } - - entry = readdir(dir); - } - closedir(dir); - } - } -# endif -} - -#if _HAVE_ZIP -/** - @param path The zipfile name (no trailing slash) - @param prefix Directory inside the zipfile. No leading slash, must have trailing slash if non-empty. - @param file Name inside the zipfile that we are testing to see if it matches prefix + "*" - */ -static void _zip_addEntry(const std::string& path, - const std::string& prefix, - const std::string& file, - Set<std::string>& files, - bool wantFiles, - bool includePath) { - - // Make certain we are within the desired parent folder (prefix) - if (beginsWith(file, prefix)) { - // validityTest was prefix/file - - // Extract everything to the right of the prefix - std::string s = file.substr(prefix.length()); - - if (s == "") { - // This was the name of the prefix - return; - } - - // See if there are any slashes - size_t slashPos = s.find('/'); - - bool add = false; - - if (slashPos == std::string::npos) { - // No slashes, so s must be a file - add = wantFiles; - } else if (! wantFiles) { - // Not all zipfiles list directories as explicit entries. - // Because of this, if we're looking for directories and see - // any path longer than prefix, we must add the subdirectory. - // The Set will fix duplicates for us. - s = s.substr(0, slashPos); - add = true; - } - - if (add) { - if (includePath) { - files.insert(path + "/" + prefix + s); - } else { - files.insert(s); - } - } - } -} -#endif - -static void getFileOrDirListZip(const std::string& path, - const std::string& prefix, - Array<std::string>& files, - bool wantFiles, - bool includePath){ -#if _HAVE_ZIP - struct zip *z = zip_open( path.c_str(), ZIP_CHECKCONS, NULL ); - - Set<std::string> fileSet; - - int count = zip_get_num_files( z ); - for( int i = 0; i < count; ++i ) { - struct zip_stat info; - zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required. - zip_stat_index( z, i, ZIP_FL_NOCASE, &info ); - _zip_addEntry(path, prefix, info.name, fileSet, wantFiles, includePath); - } - - zip_close( z ); - - fileSet.getMembers(files); -#endif -} - - -static void determineFileOrDirList( - const std::string& filespec, - Array<std::string>& files, - bool wantFiles, - bool includePath) { - - // if it is a .zip, prefix will specify the folder within - // whose contents we want to see - std::string prefix = ""; - std::string path = filenamePath(filespec); - - if ((path.size() > 0) && isSlash(path[path.size() - 1])) { - // Strip the trailing slash - path = path.substr(0, path.length() -1); - } - - if ((path == "") || fileExists(path, false)) { - if ((path != "") && isZipfile(path)) { - // .zip should only work if * is specified as the Base + Ext - // Here, we have been asked for the root's contents - debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard"); - getFileOrDirListZip(path, prefix, files, wantFiles, includePath); - } else { - // It is a normal directory - getFileOrDirListNormal(filespec, files, wantFiles, includePath); - } - } else if (zipfileExists(filenamePath(filespec), path, prefix)) { - // .zip should only work if * is specified as the Base + Ext - // Here, we have been asked for the contents of a folder within the .zip - debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard"); - getFileOrDirListZip(path, prefix, files, wantFiles, includePath); - } -} - - -void getFiles(const std::string& filespec, - Array<std::string>& files, - bool includePath) { - - determineFileOrDirList(filespec, files, true, includePath); -} - - -void getDirs( - const std::string& filespec, - Array<std::string>& files, - bool includePath) { - - determineFileOrDirList(filespec, files, false, includePath); -} - - -std::string filenameBaseExt(const std::string& filename) { - int i = filename.rfind("/"); - int j = filename.rfind("\\"); - - if ((j > i) && (j >= 0)) { - i = j; - } - -# ifdef G3D_WIN32 - j = filename.rfind(":"); - if ((i == -1) && (j >= 0)) { - i = j; - } -# endif - - if (i == -1) { - return filename; - } else { - return filename.substr(i + 1, filename.length() - i); - } -} - - -std::string filenameBase(const std::string& s) { - std::string drive; - std::string base; - std::string ext; - Array<std::string> path; - - parseFilename(s, drive, path, base, ext); - return base; -} - - -std::string filenameExt(const std::string& filename) { - int i = filename.rfind("."); - if (i >= 0) { - return filename.substr(i + 1, filename.length() - i); - } else { - return ""; - } -} - - -std::string filenamePath(const std::string& filename) { - int i = filename.rfind("/"); - int j = filename.rfind("\\"); - - if ((j > i) && (j >= 0)) { - i = j; - } - -# ifdef G3D_WIN32 - j = filename.rfind(":"); - if ((i == -1) && (j >= 0)) { - i = j; - } -# endif - - if (i == -1) { - return ""; - } else { - return filename.substr(0, i+1); - } -} - - -bool isZipfile(const std::string& filename) { - - FILE* f = fopen(filename.c_str(), "r"); - if (f == NULL) { - return false; - } - uint8 header[4]; - fread(header, 4, 1, f); - - const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04}; - for (int i = 0; i < 4; ++i) { - if (header[i] != zipHeader[i]) { - fclose(f); - return false; - } - } - - fclose(f); - return true; -} - - -bool isDirectory(const std::string& filename) { - struct _stat st; - bool exists = _stat(filename.c_str(), &st) != -1; - return exists && ((st.st_mode & S_IFDIR) != 0); -} - - -bool filenameContainsWildcards(const std::string& filename) { - return (filename.find('*') != std::string::npos) || (filename.find('?') != std::string::npos); -} - - -bool fileIsNewer(const std::string& src, const std::string& dst) { - struct _stat sts; - bool sexists = _stat(src.c_str(), &sts) != -1; - - struct _stat dts; - bool dexists = _stat(dst.c_str(), &dts) != -1; - - return sexists && ((! dexists) || (sts.st_mtime > dts.st_mtime)); -} - - -Array<std::string> filesUsed() { - Array<std::string> f; - _internal::currentFilesUsed.getMembers(f); - return f; -} - -} - -#ifndef G3D_WIN32 - #undef _stat -#endif |