diff --git a/src/fileio.cpp b/src/fileio.cpp index 8201b7c0f6..9e141c6e53 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -956,3 +956,98 @@ void *ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize) *lenp = len; return mem; } + + +/** + * Scan a single directory (and recursively it's children) and add + * any graphics sets that are found. + * @param extension the extension of files to search for. + * @param path full path we're currently at + * @param basepath_length from where in the path are we 'based' on the search path + */ +static uint ScanPath(FileScanner *fs, const char *extension, const char *path, size_t basepath_length) +{ + extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb); + + uint num = 0; + struct stat sb; + struct dirent *dirent; + DIR *dir; + + if (path == NULL || (dir = ttd_opendir(path)) == NULL) return 0; + + while ((dirent = readdir(dir)) != NULL) { + const char *d_name = FS2OTTD(dirent->d_name); + char filename[MAX_PATH]; + + if (!FiosIsValidFile(path, dirent, &sb)) continue; + + snprintf(filename, lengthof(filename), "%s%s", path, d_name); + + if (sb.st_mode & S_IFDIR) { + /* Directory */ + if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue; + AppendPathSeparator(filename, lengthof(filename)); + num += ScanPath(fs, extension, filename, basepath_length); + } else if (sb.st_mode & S_IFREG) { + /* File */ + char *ext = strrchr(filename, '.'); + + /* If no extension or extension isn't .grf, skip the file */ + if (ext == NULL) continue; + if (strcasecmp(ext, extension) != 0) continue; + + if (fs->AddFile(filename, basepath_length)) num++; + } + } + + closedir(dir); + + return num; +} + +/** + * Scan the given tar and add graphics sets when it finds one. + * @param extension the extension of files to search for. + * @param tar the tar to search in. + */ +static uint ScanTar(FileScanner *fs, const char *extension, TarFileList::iterator tar) +{ + uint num = 0; + const char *filename = (*tar).first.c_str(); + const char *ext = strrchr(filename, '.'); + + /* If no extension or extension isn't .grf, skip the file */ + if (ext == NULL) return false; + if (strcasecmp(ext, extension) != 0) return false; + + if (fs->AddFile(filename, 0)) num++; + + return num; +} + +/** + * Scan for files with the given extention in the given search path. + * @param extension the extension of files to search for. + * @param sp the sub directory to search in. + * @param tars whether to search in the tars too. + * @return the number of found files, i.e. the number of times that + * AddFile returned true. + */ +uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars) +{ + Searchpath sp; + char path[MAX_PATH]; + TarFileList::iterator tar; + uint num = 0; + + FOR_ALL_SEARCHPATHS(sp) { + FioAppendDirectory(path, MAX_PATH, sp, sd); + num += ScanPath(this, extension, path, strlen(path)); + } + FOR_ALL_TARS(tar) { + num += ScanTar(this, extension, tar); + } + + return num; +} diff --git a/src/fileio.h b/src/fileio.h index 6d4aed2b40..7c8a802214 100644 --- a/src/fileio.h +++ b/src/fileio.h @@ -96,4 +96,20 @@ bool FileExists(const char *filename); extern char *_personal_dir; ///< custom directory for personal settings, saves, newgrf, etc. +/** Helper for scanning for files with a given name */ +class FileScanner +{ +public: + uint Scan(const char *extension, Subdirectory sd, bool tars = true); + + /** + * Add a file with the given filename. + * @param filename the full path to the file to read + * @param basepath_length amount of characters to chop of before to get a + * filename relative to the search path. + * @return true if the file is added. + */ + virtual bool AddFile(const char *filename, size_t basepath_length) = 0; +}; + #endif /* FILEIO_H */ diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index a8aeb2f63f..6faeb8d773 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -15,10 +15,8 @@ #include "gamelog.h" #include "network/network_type.h" -#include "tar_type.h" #include "fileio.h" #include "fios.h" -#include GRFConfig *_all_grfs; @@ -267,10 +265,23 @@ compatible_grf: return res; } -static bool ScanPathAddGrf(const char *filename) +/** Helper for scanning for files with GRF as extension */ +class GRFFileScanner : FileScanner { +public: + /* virtual */ bool AddFile(const char *filename, size_t basepath_length); + + /** Do the scan for GRFs. */ + static uint DoScan() + { + GRFFileScanner fs; + return fs.Scan(".grf", DATA_DIR); + } +}; + +bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length) { GRFConfig *c = CallocT(1); - c->filename = strdup(filename); + c->filename = strdup(filename + basepath_length); bool added = true; if (FillGRFDetails(c, false)) { @@ -313,63 +324,6 @@ static bool ScanPathAddGrf(const char *filename) return added; } -/* Scan a path for NewGRFs */ -static uint ScanPath(const char *path, size_t basepath_length) -{ - extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb); - - uint num = 0; - struct stat sb; - struct dirent *dirent; - DIR *dir; - - if (path == NULL || (dir = ttd_opendir(path)) == NULL) return 0; - - while ((dirent = readdir(dir)) != NULL) { - const char *d_name = FS2OTTD(dirent->d_name); - char filename[MAX_PATH]; - - if (!FiosIsValidFile(path, dirent, &sb)) continue; - - snprintf(filename, lengthof(filename), "%s%s", path, d_name); - - if (sb.st_mode & S_IFDIR) { - /* Directory */ - if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue; - AppendPathSeparator(filename, lengthof(filename)); - num += ScanPath(filename, basepath_length); - } else if (sb.st_mode & S_IFREG) { - /* File */ - char *ext = strrchr(filename, '.'); - - /* If no extension or extension isn't .grf, skip the file */ - if (ext == NULL) continue; - if (strcasecmp(ext, ".grf") != 0) continue; - - if (ScanPathAddGrf(filename + basepath_length)) num++; - } - } - - closedir(dir); - - return num; -} - -static uint ScanTar(TarFileList::iterator tar) -{ - uint num = 0; - const char *filename = (*tar).first.c_str(); - const char *ext = strrchr(filename, '.'); - - /* If no extension or extension isn't .grf, skip the file */ - if (ext == NULL) return false; - if (strcasecmp(ext, ".grf") != 0) return false; - - if (ScanPathAddGrf(filename)) num++; - - return num; -} - /** * Simple sorter for GRFS * @param p1 the first GRFConfig * @@ -388,21 +342,10 @@ static int CDECL GRFSorter(const void *p1, const void *p2) /* Scan for all NewGRFs */ void ScanNewGRFFiles() { - Searchpath sp; - char path[MAX_PATH]; - TarFileList::iterator tar; - uint num = 0; - ClearGRFConfigList(&_all_grfs); DEBUG(grf, 1, "Scanning for NewGRFs"); - FOR_ALL_SEARCHPATHS(sp) { - FioAppendDirectory(path, MAX_PATH, sp, DATA_DIR); - num += ScanPath(path, strlen(path)); - } - FOR_ALL_TARS(tar) { - num += ScanTar(tar); - } + uint num = GRFFileScanner::DoScan(); DEBUG(grf, 1, "Scan complete, found %d files", num); if (num == 0 || _all_grfs == NULL) return;