ParameterList.cc
00001
00002
00003
00004
00005 #include "ParameterList.hh"
00006 #include "Parameter.hh"
00007 #include <sstream>
00008 #include "Message.hh"
00009 #include "ConfigHandler.hh"
00010 #include <stdexcept>
00011 #include <iomanip>
00012
00013 ParameterList::~ParameterList()
00014 {
00015
00016 }
00017
00018 ParameterList::ParameterList(const ParameterList& right) :
00019 VParameterNode(right._default_key, right._helptext)
00020 {
00021 _node_type = PARAMETER_LIST;
00022 CopyPlistRelative(right);
00023 }
00024
00025 ParameterList& ParameterList::operator=(const ParameterList& right)
00026 {
00027 _deleter.clear();
00028 _parameters.clear();
00029 return *this;
00030 }
00031
00032 void ParameterList::CopyPlistRelative(const ParameterList& right)
00033 {
00034 ParMap::const_iterator it;
00035 for(it = right._parameters.begin(); it != right._parameters.end(); ++it){
00036 VParameterNode* newnode = it->second->Clone(&right, this);
00037 switch(newnode->GetNodeType()){
00038 case FUNCTION:
00039 case PARAMETER:{
00040 boost::shared_ptr<VParameterNode> ptr(newnode);
00041 _deleter.push_back(ptr);
00042 _parameters.insert(std::make_pair(it->first,newnode));
00043 break;
00044 }
00045 case PARAMETER_LIST:
00046 _parameters.insert(std::make_pair(it->first, newnode));
00047 break;
00048 default:
00049 break;
00050 }
00051
00052 }
00053 }
00054
00055
00056 VParameterNode* const ParameterList::GetParameter(const std::string& key){
00057 ParMap::iterator it = _parameters.find(key);
00058 if(it != _parameters.end())
00059 return it->second;
00060 else
00061 return 0;
00062 }
00063
00064 std::istream& ParameterList::ReadFrom(std::istream& in, bool single)
00065 {
00066 if(_parameters.empty())
00067 InitializeParameterList();
00068 char next = ' ';
00069
00070 while ( in.get(next) ){
00071
00072 if( next == ')' || next == '}' )
00073 break;
00074
00075 if( next == ' ' || next == ',' || next == '\t' || next == '\n'
00076 || next == '(' || next == '{' || next == '|' || next == ';')
00077 continue;
00078
00079 if( next =='#' ){
00080 std::string dummy;
00081 std::getline(in,dummy);
00082 continue;
00083 }
00084
00085 if( next == '@' ){
00086 std::string func;
00087 in>>func;
00088 if(func == "include"){
00089 std::string fname;
00090 in>>fname;
00091 std::string filepath = ConfigHandler::GetInstance()->FindConfigFile(fname);
00092 if(filepath == "")
00093 throw std::invalid_argument(fname);
00094 Message(DEBUG)<<"including file "<<filepath<<std::endl;
00095 ReadFromFile(filepath.c_str());
00096 continue;
00097 }
00098 else if (func == "copy"){
00099 std::string par1, par2;;
00100 in>>par1>>par2;
00101 Message(DEBUG)<<"Copying all settings of "<<par1<<" to "<<par2<<"\n";
00102 ParMap::iterator it1 = _parameters.find(par1);
00103 ParMap::iterator it2 = _parameters.find(par2);
00104 if(it1 == _parameters.end() || it2 == _parameters.end()){
00105 Message(EXCEPTION)<<"Unable to find one of the parameters "<<par1
00106 <<" or "<<par2<<" to copy!\n";
00107 throw std::invalid_argument(par1+","+par2);
00108 }
00109 std::stringstream temp;
00110 (it1->second)->WriteTo(temp);
00111 (it2->second)->ReadFrom(temp);
00112 continue;
00113 }
00114 else{
00115 Message(WARNING)<<"Ignoring unknown command: @"<<func<<std::endl;
00116 continue;
00117 }
00118 }
00119
00120
00121 in.unget();
00122
00123 std::string bigkey;
00124 if( !(in>>bigkey) ){
00125
00126 throw std::invalid_argument("Unabled to read parameter list");
00127 return in;
00128 }
00129
00130 std::vector<std::string> keylist;
00131 size_t searchstart=0;
00132 size_t pos;
00133 while( (pos = bigkey.find(',',searchstart)) != std::string::npos){
00134 keylist.push_back(bigkey.substr(searchstart,(pos-searchstart)));
00135 searchstart = pos+1;
00136 if(searchstart >= bigkey.size()) break;
00137 }
00138
00139 keylist.push_back(bigkey.substr(searchstart));
00140
00141
00142 std::streampos start = in.tellg();
00143 for(size_t ikey = 0; ikey<keylist.size(); ++ikey){
00144 if(ikey>0)
00145 in.seekg(start);
00146
00147 std::string key = keylist[ikey];
00148
00149 bool sendsingle = false;
00150 std::string::size_type pos = key.find('.',0);
00151 if( pos != std::string::npos){
00152
00153 if(ikey != keylist.size()-1){
00154 Message(EXCEPTION)<<"Configuration parameters with '.' are "
00155 <<"only allowed last in a comma set!\n";
00156 throw std::invalid_argument(key);
00157 }
00158
00159 sendsingle=true;
00160
00161 in.seekg( in.tellg() - std::streampos(key.length()-pos - 1));
00162
00163 key = key.substr(0,pos);
00164 }
00165
00166
00167 if( key.at(key.length()-1) == '*'){
00168 key.resize( key.size() - 1 );
00169 int wildcardkeysfound = 0;
00170 for(int i=0; i<100; ++i){
00171 std::stringstream keystream;
00172 keystream<<key<<i;
00173 if(_parameters.find(keystream.str()) == _parameters.end())
00174 break;
00175 keylist.push_back(keystream.str());
00176 ++wildcardkeysfound;
00177 }
00178
00179 if(wildcardkeysfound==0){
00180 Message(EXCEPTION)<<"No keys matching wildcard '"<<key<<"*'!\n";
00181 throw std::invalid_argument(key+"*");
00182 }
00183 continue;
00184 }
00185
00186
00187 ParMap::iterator mapit;
00188 mapit = _parameters.find(key);
00189 if( mapit == _parameters.end() ){
00190
00191 Message e(EXCEPTION);
00192 e<<"Key "<<key<<" is not a valid parameter for ParameterList '"
00193 <<GetDefaultKey()<<"'"<<std::endl;
00194 throw std::invalid_argument(e.str());
00195 return in;
00196 }
00197 VParameterNode* child = (mapit->second);
00198 child->ReadFrom(in,sendsingle);
00199 }
00200 if(single)
00201 return in;
00202 }
00203 return in;
00204
00205 }
00206
00207 std::ostream& ParameterList::WriteTo( std::ostream& out, bool showhelp,
00208 int indent) const
00209 {
00210
00211
00212 std::stringstream dummy;
00213 dummy<<'\n';
00214 for(int i=0; i < indent; i++)
00215 dummy<<" ";
00216 const std::string newline = dummy.str();
00217
00218
00219 out<<"( "<<newline;
00220 ParMap::const_iterator mapit;
00221 mapit = _parameters.begin();
00222
00223 while( !out.fail() && mapit != _parameters.end() ){
00224 if(mapit->second->haswrite){
00225 int node_type = mapit->second->GetNodeType();
00226 if(showhelp) out<<newline<<"# "<<mapit->second->GetHelpText()<<newline;
00227 if(node_type == FUNCTION)
00228 out<<"#";
00229 out<<(mapit->first)<<" ";
00230 if(node_type == FUNCTION)
00231 out<<newline;
00232 mapit->second->WriteTo(out, showhelp, indent+1);
00233 out<<newline;
00234 }
00235 ++mapit;
00236 }
00237 out<<(showhelp ? newline : "")<<")" << (showhelp ? " #end list" : "");
00238 out.flush();
00239 return out;
00240 }
00241
00242 int ParameterList::PrintHelp(const std::string& myname) const
00243 {
00244
00245 VParameterNode::PrintHelp(myname);
00246 std::cout<<"List of sub-parameters:\n";
00247 int parnumber=0;
00248 ParMap::const_iterator mapit;
00249 for( mapit = _parameters.begin() ; mapit != _parameters.end(); ++mapit){
00250 std::cout<<" "<<std::left<<std::setw(5)<<std::setfill(' ')<<++parnumber
00251 <<(mapit->first)<<std::endl;
00252 }
00253 std::cout<<"\nEnter n) for more information about parameter n"
00254 <<"\n -n) to go up n levels"
00255 <<"\n 0) to quit the help browser"<<std::endl;
00256
00257 int response=0;
00258 std::cin >> response;
00259 if(response == 0)
00260 return 1;
00261 else if(response > (int)_parameters.size() ){
00262 std::cerr<<"The number you entered was too large!\n";
00263 return PrintHelp(myname);
00264 }
00265 else if(response > 0){
00266 mapit = _parameters.begin();
00267 for(int i=0; i < response-1; i++) ++mapit;
00268 response = (mapit->second)->PrintHelp(mapit->first);
00269 }
00270
00271 if(response == 0)
00272 return PrintHelp(myname);
00273 if(response < 0)
00274 response++;
00275
00276 return response;
00277 }
00278
00279