1 /* $Id: jigdoconfig.hh,v 1.5 2005/04/09 14:44:50 atterer Exp $ -*- C++ -*- 2 __ _ 3 |_) /| Copyright (C) 2001-2002 | richard@ 4 | \/�| Richard Atterer | atterer.net 5 � '` � 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License, version 2. See 8 the file COPYING for details. 9 10 *//** @file 11 12 Representation for config data in a .jigdo file - based on ConfigFile 13 14 Mostly, this class just "forwards" requests by making the 15 appropriate calls to the ConfigFile object, with one exception: It 16 caches the labels in the [Servers] section and detects loops. 17 18 */ 19 20 #ifndef JIGDOCONFIG_HH 21 #define JIGDOCONFIG_HH 22 23 #include <map> 24 #include <string> 25 #include <vector> 26 27 #include <configfile.hh> 28 //______________________________________________________________________ 29 30 /** Representation for config data in a .jigdo file - based on ConfigFile */ 31 class JigdoConfig { 32 private: 33 /* multimap doesn't make guarantees about order of inserted values 34 with equal key, which needs to be preserved in our case. */ 35 typedef map<string,vector<string> > Map; 36 //________________________________________ 37 38 public: errorAnyReporter39 /** To be implemented by anyone who is interested in errors/info from the 40 JigdoConfig */ 41 class ProgressReporter { 42 public: 43 virtual ~ProgressReporter() { } 44 virtual void error(const string& message); 45 virtual void info(const string& message); 46 }; 47 //________________________________________ 48 49 #if 0 /* Use same function from net/uri.hh */ 50 /** Helper function: Given a string, return 0 if the string has no "Label:" 51 prefix, otherwise return the offset of the ':'. The "Label" portion of 52 the string can contain *any* character except '/' and 53 whitespace/control characters */ 54 static inline unsigned findLabelColon(const string& s); 55 #endif 56 //________________________________________ 57 58 /** Open file for input and create a ConfigFile object */ 59 JigdoConfig(const char* jigdoFile, ProgressReporter& pr); 60 JigdoConfig(const string& jigdoFile, ProgressReporter& pr); 61 /** Take over possession of existing ConfigFile - configFile will be 62 deleted in ~JigdoConfig()! jigdoFile argument is not used except for 63 error messages. */ 64 JigdoConfig(const char* jigdoFile, ConfigFile* configFile, 65 ProgressReporter& pr); 66 JigdoConfig(const string& jigdoFile, ConfigFile* configFile, 67 ProgressReporter& pr); 68 ~JigdoConfig() { delete config; } 69 ConfigFile& configFile() { return *config; } 70 //________________________________________ 71 72 /** Prepare internal map from label name to URIs. Is called automatically 73 during JigdoConfig(), but must be called manually afterwards whenever 74 any entry in the ConfigFile's "[Servers]" section changes. May throw 75 an Error if the jigdo file format version is not supported. */ 76 void rescan(); 77 78 /** Change reporter for error messages */ 79 inline void setReporter(ProgressReporter& pr); 80 81 /** Given an URI-style string like "MyServer:dir/foo/file.gz", do 82 label lookup (looking for [Servers] entries like "MyServer=...") 83 and return the resulting strings, e.g. 84 "ftp://mysite.com/dir/foo/file.gz". The class will enumerate all 85 the possible URIs. NB: After a jc.rescan(), no further calls to 86 next() of existing Lookups for that JigdoConfig are allowed. 87 Also, query must stay valid throughout the lifetime of Lookup, 88 since a reference to it is maintained. */ 89 class Lookup { 90 public: 91 inline Lookup(const JigdoConfig& jc, const string& query); 92 /** If true returned, result has been overwritten with next value. 93 Otherwise, end of list has been reached and result is 94 unchanged. */ 95 inline bool next(string& result); 96 // Default copy ctor and dtor 97 private: 98 const JigdoConfig& config; 99 // "MyServer:dir/foo/file.gz" or null: next() returns false 100 const string* uri; 101 string::size_type colon; // Offset of ':' in query 102 // Pointer in list for "MyServer" mappings; pointer to end of list 103 vector<string>::const_iterator cur, end; 104 }; 105 friend class Lookup; 106 //________________________________________ 107 108 private: 109 110 /* Adds filename and line number before reporting. This is used by 111 JigdoConfig to talk to ConfigFile. */ 112 struct ForwardReporter : ConfigFile::ProgressReporter { 113 inline ForwardReporter(JigdoConfig::ProgressReporter& pr, 114 const string& file); 115 inline ForwardReporter(JigdoConfig::ProgressReporter& pr, 116 const char* file); 117 virtual ~ForwardReporter() { } 118 virtual void error(const string& message, const size_t lineNr = 0); 119 virtual void info(const string& message, const size_t lineNr = 0); 120 JigdoConfig::ProgressReporter* reporter; 121 string fileName; 122 }; 123 //________________________________________ 124 125 struct ServerLine { 126 ConfigFile::iterator line; 127 size_t labelStart, labelEnd, valueStart; 128 }; 129 Map::iterator rescan_addLabel(list<ServerLine>& entries, 130 const string& label, bool& printError); 131 inline void rescan_makeSubst(list<ServerLine>& entries, Map::iterator mapl, 132 const ServerLine& l, bool& printError); 133 void scanVersionInfo(); // Check for supported file format version number 134 135 ConfigFile* config; binName()136 Map serverMap; 137 ForwardReporter freporter; 138 }; 139 //______________________________________________________________________ binName()140 141 JigdoConfig::ForwardReporter::ForwardReporter( 142 JigdoConfig::ProgressReporter& pr, const string& file) 143 : reporter(&pr), fileName(file) { } 144 145 JigdoConfig::ForwardReporter::ForwardReporter( 146 JigdoConfig::ProgressReporter& pr, const char* file) 147 : reporter(&pr), fileName(file) { } 148 149 void JigdoConfig::setReporter(ProgressReporter& pr) { 150 freporter.reporter = ≺ 151 } 152 //________________________________________ 153 154 JigdoConfig::Lookup::Lookup(const JigdoConfig& jc, const string& query) 155 : config(jc), uri(&query), colon(query.find(':')), cur() { 156 /* colon == string::npos means: The URI doesn't contain a ':', or it 157 does but the label before it ("MyServer") isn't listed in the 158 mapping, or the label is listed but the corresponding 159 vector<string> is empty. In all these cases, the Lookup will only 160 return one string - the original query. */ 161 if (colon != string::npos) { 162 string label(query, 0, colon); 163 Map::const_iterator vec = config.serverMap.find(label); 164 ++colon; 165 if (vec != config.serverMap.end() && vec->second.size() != 0) { 166 cur = vec->second.begin(); 167 end = vec->second.end(); 168 } else { 169 colon = string::npos; 170 } 171 } 172 } 173 174 bool JigdoConfig::Lookup::next(string& result) { 175 if (uri == 0) return false; 176 if (colon == string::npos) { // Only return one value 177 result = *uri; 178 uri = 0; 179 return true; 180 } 181 // Iterate through vector 182 result = *cur; 183 result.append(*uri, colon, string::npos); 184 ++cur; 185 if (cur == end) uri = 0; 186 return true; 187 } 188 189 #endif 190