00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <sstream>
00034 #include <fstream>
00035 #include <iostream>
00036 #include <iomanip>
00037 #include <string>
00038 #include <cstring>
00039 #include <cctype>
00040 #include "string_utils.h"
00041
00042 using namespace std;
00043
00044 string trim (const string &orig)
00045 {
00046 string::size_type p1=orig.find_first_not_of(" \t");
00047 if (p1==string::npos) return "";
00048 string::size_type p2=orig.find_last_not_of(" \t");
00049 return orig.substr(p1,p2-p1+1);
00050 }
00051
00052 template<typename T> string dataToString (const T &x)
00053 {
00054 ostringstream strstrm;
00055 strstrm << x;
00056 return trim(strstrm.str());
00057 }
00058
00059 template<> string dataToString (const bool &x)
00060 { return x ? "T" : "F"; }
00061 template<> string dataToString (const string &x)
00062 { return trim(x); }
00063 template<> string dataToString (const float &x)
00064 {
00065 ostringstream strstrm;
00066 strstrm << setprecision(8) << x;
00067 return trim(strstrm.str());
00068 }
00069 template<> string dataToString (const double &x)
00070 {
00071 ostringstream strstrm;
00072 strstrm << setprecision(16) << x;
00073 return trim(strstrm.str());
00074 }
00075 template<> string dataToString (const long double &x)
00076 {
00077 ostringstream strstrm;
00078 strstrm << setprecision(25) << x;
00079 return trim(strstrm.str());
00080 }
00081
00082 template string dataToString (const signed char &x);
00083 template string dataToString (const unsigned char &x);
00084 template string dataToString (const short &x);
00085 template string dataToString (const unsigned short &x);
00086 template string dataToString (const int &x);
00087 template string dataToString (const unsigned int &x);
00088 template string dataToString (const long &x);
00089 template string dataToString (const unsigned long &x);
00090 template string dataToString (const long long &x);
00091 template string dataToString (const unsigned long long &x);
00092
00093 string intToString(int64 x, tsize width)
00094 {
00095 ostringstream strstrm;
00096 (x>=0) ? strstrm << setw(width) << setfill('0') << x
00097 : strstrm << "-" << setw(width-1) << setfill('0') << -x;
00098 string res = strstrm.str();
00099 planck_assert(res.size()==width,"number too large");
00100 return trim(res);
00101 }
00102
00103 namespace {
00104
00105 void end_stringToData (const string &x, const char *tn, istringstream &strstrm)
00106 {
00107 string error = string("conversion error in stringToData<")+tn+">(\""+x+"\")";
00108 planck_assert (strstrm,error);
00109 string rest;
00110 strstrm >> rest;
00111
00112 planck_assert (rest.length()==0,error);
00113 }
00114
00115 }
00116
00117 template<typename T> void stringToData (const string &x, T &value)
00118 {
00119 istringstream strstrm(x);
00120 strstrm >> value;
00121 end_stringToData (x,type2typename<T>(),strstrm);
00122 }
00123
00124 template<> void stringToData (const string &x, string &value)
00125 { value = trim(x); }
00126
00127 template<> void stringToData (const string &x, bool &value)
00128 {
00129 const char *x2 = x.c_str();
00130 const char *fval[] = {"F","f","n","N","false",".false.","FALSE",".FALSE." };
00131 const char *tval[] = {"T","t","y","Y","true",".true.","TRUE",".TRUE." };
00132 for (tsize i=0; i< sizeof(fval)/sizeof(fval[0]); ++i)
00133 if (strcmp(x2,fval[i])==0) { value=false; return; }
00134 for (tsize i=0; i< sizeof(tval)/sizeof(tval[0]); ++i)
00135 if (strcmp(x2,tval[i])==0) { value=true; return; }
00136 planck_fail("conversion error in stringToData<bool>(\""+x+"\")");
00137 }
00138
00139 template void stringToData (const string &x, signed char &value);
00140 template void stringToData (const string &x, unsigned char &value);
00141 template void stringToData (const string &x, short &value);
00142 template void stringToData (const string &x, unsigned short &value);
00143 template void stringToData (const string &x, int &value);
00144 template void stringToData (const string &x, unsigned int &value);
00145 template void stringToData (const string &x, long &value);
00146 template void stringToData (const string &x, unsigned long &value);
00147 template void stringToData (const string &x, long long &value);
00148 template void stringToData (const string &x, unsigned long long &value);
00149 template void stringToData (const string &x, float &value);
00150 template void stringToData (const string &x, double &value);
00151 template void stringToData (const string &x, long double &value);
00152
00153 bool equal_nocase (const string &a, const string &b)
00154 {
00155 if (a.size()!=b.size()) return false;
00156 for (tsize m=0; m<a.size(); ++m)
00157 if (tolower(a[m])!=tolower(b[m])) return false;
00158 return true;
00159 }
00160
00161 string tolower(const string &input)
00162 {
00163 string result=input;
00164 for (tsize m=0; m<result.size(); ++m)
00165 result[m]=char(tolower(result[m]));
00166 return result;
00167 }
00168
00169 void parse_file (const string &filename, map<string,string> &dict)
00170 {
00171 int lineno=0;
00172 dict.clear();
00173 ifstream inp(filename.c_str());
00174 planck_assert (inp,"Could not open parameter file '"+filename+"'.");
00175 while (inp)
00176 {
00177 string line;
00178 getline(inp, line);
00179 ++lineno;
00180
00181 line=line.substr(0,line.find("\r"));
00182 line=line.substr(0,line.find("#"));
00183 line=trim(line);
00184 if (line.size()>0)
00185 {
00186 string::size_type eqpos=line.find("=");
00187 if (eqpos!=string::npos)
00188 {
00189 string key=trim(line.substr(0,eqpos)),
00190 value=trim(line.substr(eqpos+1,string::npos));
00191 if (key=="")
00192 cerr << "Warning: empty key in '" << filename << "', line "
00193 << lineno << endl;
00194 else
00195 {
00196 if (dict.find(key)!=dict.end())
00197 cerr << "Warning: key '" << key << "' multiply defined in '"
00198 << filename << "', line " << lineno << endl;
00199 dict[key]=value;
00200 }
00201 }
00202 else
00203 cerr << "Warning: unrecognized format in '" << filename << "', line "
00204 << lineno << ":\n" << line << endl;
00205 }
00206 }
00207 }
00208
00209 namespace {
00210
00211 bool isParam (const string &s)
00212 {
00213 if (s.size()<2) return false;
00214 if (s[0]!='-') return false;
00215 return !(isdigit(s[1]) || (s[1]=='.'));
00216 }
00217
00218 }
00219
00220 void parse_cmdline_classic (int argc, const char **argv,
00221 const vector<string> &leading_args, map<string,string> &dict)
00222 {
00223 dict.clear();
00224 planck_assert(tsize(argc)>leading_args.size(),"not enough arguments");
00225 for (tsize i=0; i<leading_args.size(); ++i)
00226 dict[leading_args[i]] = argv[i+1];
00227 int curarg=leading_args.size()+1;
00228 while (curarg<argc)
00229 {
00230 string param=argv[curarg];
00231 planck_assert(isParam(param),"unrecognized command line format");
00232 if ((curarg==argc-1) || isParam(argv[curarg+1]))
00233 {
00234 dict[param.substr(1)]="true";
00235 ++curarg;
00236 }
00237 else
00238 {
00239 dict[param.substr(1)]=argv[curarg+1];
00240 curarg+=2;
00241 }
00242 }
00243 }
00244
00245 void parse_cmdline_classic (int argc, const char **argv,
00246 map<string,string> &dict)
00247 { parse_cmdline_classic (argc, argv, vector<string>(), dict); }
00248
00249 void parse_cmdline_equalsign (int argc, const char **argv,
00250 const vector<string> &leading_args, map<string,string> &dict)
00251 {
00252 dict.clear();
00253 planck_assert(tsize(argc)>leading_args.size(),"not enough arguments");
00254 for (tsize i=0; i<leading_args.size(); ++i)
00255 dict[leading_args[i]] = argv[i+1];
00256 for (int i=leading_args.size()+1; i<argc; ++i)
00257 {
00258 string arg=trim(argv[i]);
00259 if (arg.size()>0)
00260 {
00261 string::size_type eqpos=arg.find("=");
00262 if (eqpos!=string::npos)
00263 {
00264 string key=trim(arg.substr(0,eqpos)),
00265 value=trim(arg.substr(eqpos+1,string::npos));
00266 if (key=="")
00267 cerr << "Warning: empty key in argument'" << arg << "'" << endl;
00268 else
00269 {
00270 if (dict.find(key)!=dict.end())
00271 cerr << "Warning: key '" << key << "' multiply defined" << endl;
00272 dict[key]=value;
00273 }
00274 }
00275 else
00276 cerr << "Warning: unrecognized format in argument '" << arg << "'"
00277 << endl;
00278 }
00279 }
00280 }
00281
00282 void parse_cmdline_equalsign (int argc, const char **argv,
00283 map<string,string> &dict)
00284 { parse_cmdline_equalsign (argc, argv, vector<string>(), dict); }
00285
00286 namespace {
00287
00288 template<typename T> void split (istream &stream, vector<T> &list)
00289 {
00290 list.clear();
00291 while (stream)
00292 {
00293 string word;
00294 stream >> word;
00295 planck_assert (stream||stream.eof(),
00296 string("error while splitting stream into ") + type2typename<T>()
00297 + "components");
00298 if (stream) list.push_back(stringToData<T>(word));
00299 }
00300 }
00301
00302 }
00303
00304 template<typename T> void split (const string &inp, vector<T> &list)
00305 {
00306 istringstream stream(inp);
00307 split (stream,list);
00308 }
00309
00310 template void split (const string &inp, vector<string> &list);
00311 template void split (const string &inp, vector<float> &list);
00312 template void split (const string &inp, vector<double> &list);
00313 template void split (const string &inp, vector<int> &list);
00314 template void split (const string &inp, vector<long> &list);
00315
00316 void tokenize (const string &inp, char delim, vector<string> &list)
00317 {
00318 istringstream stream(inp);
00319 string token;
00320 list.clear();
00321 while (getline(stream,token,delim))
00322 list.push_back(token);
00323 }
00324
00325 void parse_words_from_file (const string &filename, vector<string> &words)
00326 {
00327 words.clear();
00328 ifstream inp(filename.c_str());
00329 planck_assert (inp,"Could not open file '"+filename+"'.");
00330 while (inp)
00331 {
00332 string word;
00333 inp>>word;
00334 word=trim(word);
00335 if (word!="") words.push_back(word);
00336 }
00337 }