/***** * locate.cc * Tom Prince 2005/03/24 * * Locate files in search path. *****/ #include #include "settings.h" #include "util.h" #include "locate.h" namespace settings { namespace fs { string extension(string name) { size_t n = name.rfind("."); if (n != string::npos) return name.substr(n); else return string(); } bool exists(string filename) { return ::access(filename.c_str(), R_OK) == 0; } } // namespace fs file_list_t searchPath; // Returns list of possible filenames, accounting for extensions. file_list_t mungeFileName(string id, string suffix) { string ext = fs::extension(id); file_list_t files; if (ext == "."+suffix) { files.push_back(id); files.push_back(id+"."+suffix); } else { files.push_back(id+"."+suffix); files.push_back(id); } return files; } // Join a directory with the given filename, to give the path to the file, // avoiding unsightly joins such as 'dir//file.asy' in favour of 'dir/file.asy' string join(string dir, string file, bool full) { return dir == "." ? (full ? string(getPath())+"/"+file : file) : *dir.rbegin() == '/' ? dir + file : dir + "/" + file; } // Find the appropriate file, first looking in the local directory, then the // directory given in settings, and finally the global system directory. string locateFile(string id, bool full, string suffix) { if(id.empty()) return ""; file_list_t filenames = mungeFileName(id,suffix); for (file_list_t::iterator leaf = filenames.begin(); leaf != filenames.end(); ++leaf) { #ifdef __MSDOS__ size_t p; while ((p=leaf->find('\\')) < string::npos) (*leaf)[p]='/'; if ((p=leaf->find(':')) < string::npos && p > 0) { (*leaf)[p]='/'; leaf->insert(0,"/cygdrive/"); } #endif if ((*leaf)[0] == '/') { string file = *leaf; if (fs::exists(file)) return file; } else { for (file_list_t::iterator dir = searchPath.begin(); dir != searchPath.end(); ++dir) { string file = join(*dir,*leaf,full); if (fs::exists(file)) return file; } } } return string(); } } // namespace settings