00001 #ifndef s11n_PATHFINDER_H 00002 #define s11n_PATHFINDER_H 00003 // Author: stephan beal <stephan@s11n.net> 00004 // License: Public Domain 00005 00006 00007 00008 #include <string> 00009 #include <list> 00010 #include <map> 00011 #include <iostream> 00012 00013 // #include <s11n/StringList.h> // todo: get rid of this in the public interface. 00014 00015 namespace s11n 00016 { 00017 /** 00018 path_finder searches for keys using a set of prefixes 00019 (paths) and suffixes (file extensions). 00020 00021 Example: 00022 00023 <pre> 00024 path_finder p; 00025 p.path( "/lib/lib:/usr/lib/lib" ); 00026 p.extensions( ".a:.so" ); 00027 cout << p.find( "z" ); 00028 </pre> 00029 00030 That would print an empty string if it finds nothing, or a 00031 string if it finds any of the following: 00032 00033 - z 00034 - /lib/libz 00035 - /lib/libz.a 00036 - /lib/libz.so 00037 - /usr/lib/libz 00038 - /usr/lib/libz.a 00039 - /usr/lib/libz.so 00040 00041 00042 00043 Please excuse the large number of unnecessary i/o operators 00044 in this interface: this is old code from when i started 00045 learning STL and wanted to try a lot of stuff out. :/ 00046 */ 00047 class path_finder 00048 { 00049 public: 00050 00051 /** 00052 A list type returned by some functions. 00053 */ 00054 typedef std::list<std::string> string_list; 00055 00056 00057 /** 00058 Creates object with the given path/extension list. 00059 */ 00060 path_finder( const std::string & path = std::string(), const std::string & ext = std::string(), const std::string & pathsep = ":" ); 00061 00062 virtual ~path_finder(); 00063 00064 /** 00065 Returns a ":"-separated string of all paths added via add/path(). 00066 */ 00067 std::string path_string() const; 00068 00069 /** 00070 Sets the string used as a separator for the 00071 string-based variants of path(), extentions(), etc. 00072 */ 00073 void path_separator( const std::string & sep ); 00074 00075 /** 00076 Returns the path separator string. Default is ":"; 00077 */ 00078 const std::string & path_separator() const; 00079 00080 /** 00081 Sets the path to p, which should be a path_separtor()-delimited string. 00082 Returns the number of path elements parsed from p. 00083 */ 00084 virtual unsigned int path( const std::string & p ); 00085 00086 /** 00087 Sets the path to the given list of directories. 00088 */ 00089 virtual unsigned int path( const string_list & p ); 00090 00091 /** 00092 Adds p to the path. May be path_separtor()-delimited. 00093 */ 00094 virtual void add_path( const std::string & p ); 00095 00096 /** 00097 Adds a "search extension." Sample: 00098 finder.extension( ".txt:README" ); Will now try 00099 all path combinations with the rightmost characters 00100 matching ext. Be sure to include a period if you 00101 want that searched (that is so this class can be 00102 used to find non-files and those with 00103 non-traditional extensions). 00104 */ 00105 virtual void add_extension( const std::string & ext = std::string() ); 00106 /** 00107 like extension(), but overwrites extension list. 00108 */ 00109 virtual unsigned int extensions( const std::string & ext ); 00110 /** 00111 Sets the extensions list to the given list. 00112 */ 00113 virtual unsigned int extensions( const string_list & p ); 00114 00115 /** 00116 Returns the path_separator()-delimited listed of file 00117 suffixes to use when searching for a path. 00118 */ 00119 std::string extensions_string() const; 00120 /** 00121 Returns this object's extensions list. 00122 */ 00123 const string_list & extensions() const; 00124 00125 /** 00126 Helper function to collapse a list into a string. 00127 */ 00128 std::string join_list( const string_list & list, const std::string & separator ) const; 00129 00130 /** 00131 Returns true if path is readable. 00132 */ 00133 static bool is_accessible( const std::string & path ); 00134 00135 /** 00136 Returns the "base name" of the given string: any part 00137 following the final directory separator character. 00138 */ 00139 static std::string basename( const std::string & ); 00140 00141 /** 00142 Returns a platform-dependent path separator. This 00143 is set when the class is compiled. 00144 */ 00145 static std::string dir_separator(); 00146 00147 /** 00148 Returns the full path of the given resource, provided it could be found 00149 in all paths or with all extensions added and provided it is readable. 00150 Note that this might return a relative path, especially if the 00151 resourcename passed to it immediately resolves to an existing resource. 00152 It returns an empty string if the resourcename cannot be found in 00153 the filesystem tree (or is otherwise unaccessible). 00154 00155 If check_cache is false then this function ignores 00156 it's lookup cache and searches again, otherwise it 00157 uses a cache. When caching it will always return 00158 the same result for any given resourcename. 00159 */ 00160 std::string find( const std::string & resourcename, bool check_cache = true ) const; 00161 00162 /** 00163 Returns a list of all items added via add_path() and path(). 00164 */ 00165 const string_list & path() const; 00166 00167 00168 private: 00169 string_list paths; 00170 string_list exts; 00171 std::string pathseparator; 00172 typedef std::map < std::string, std::string > StringStringMap; 00173 typedef StringStringMap::iterator StringStringIterator; 00174 mutable StringStringMap hitcache; 00175 }; 00176 00177 00178 /** 00179 operator << adds this object's path to os. 00180 */ 00181 std::ostream & operator <<( std::ostream & os, const path_finder & ); 00182 00183 /** 00184 Similar to the ostream version, it exports this 00185 object's path to the given string. 00186 */ 00187 std::string & operator <<( std::string & os, const path_finder & ); 00188 00189 /** 00190 Adds p to this object's path(). 00191 */ 00192 path_finder & operator +=( path_finder & list, const std::string & p ); 00193 00194 }; // namespace s11n 00195 #endif // s11n_PATHFINDER_H