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 *fval[] = {"f","n","false",".false."};
00130 const char *tval[] = {"t","y","true",".true."};
00131 for (tsize i=0; i< sizeof(fval)/sizeof(fval[0]); ++i)
00132 if (equal_nocase(x,fval[i])) { value=false; return; }
00133 for (tsize i=0; i< sizeof(tval)/sizeof(tval[0]); ++i)
00134 if (equal_nocase(x,tval[i])) { value=true; return; }
00135 planck_fail("conversion error in stringToData<bool>(\""+x+"\")");
00136 }
00137
00138 template void stringToData (const string &x, signed char &value);
00139 template void stringToData (const string &x, unsigned char &value);
00140 template void stringToData (const string &x, short &value);
00141 template void stringToData (const string &x, unsigned short &value);
00142 template void stringToData (const string &x, int &value);
00143 template void stringToData (const string &x, unsigned int &value);
00144 template void stringToData (const string &x, long &value);
00145 template void stringToData (const string &x, unsigned long &value);
00146 template void stringToData (const string &x, long long &value);
00147 template void stringToData (const string &x, unsigned long long &value);
00148 template void stringToData (const string &x, float &value);
00149 template void stringToData (const string &x, double &value);
00150 template void stringToData (const string &x, long double &value);
00151
00152 bool equal_nocase (const string &a, const string &b)
00153 {
00154 if (a.size()!=b.size()) return false;
00155 for (tsize m=0; m<a.size(); ++m)
00156 if (tolower(a[m])!=tolower(b[m])) return false;
00157 return true;
00158 }
00159
00160 string tolower(const string &input)
00161 {
00162 string result=input;
00163 for (tsize m=0; m<result.size(); ++m)
00164 result[m]=char(tolower(result[m]));
00165 return result;
00166 }
00167
00168 void parse_file (const string &filename, map<string,string> &dict)
00169 {
00170 int lineno=0;
00171 dict.clear();
00172 ifstream inp(filename.c_str());
00173 planck_assert (inp,"Could not open parameter file '"+filename+"'.");
00174 while (inp)
00175 {
00176 string line;
00177 getline(inp, line);
00178 ++lineno;
00179
00180 line=line.substr(0,line.find("\r"));
00181 line=line.substr(0,line.find("#"));
00182 line=trim(line);
00183 if (line.size()>0)
00184 {
00185 string::size_type eqpos=line.find("=");
00186 if (eqpos!=string::npos)
00187 {
00188 string key=trim(line.substr(0,eqpos)),
00189 value=trim(line.substr(eqpos+1,string::npos));
00190 if (key=="")
00191 cerr << "Warning: empty key in '" << filename << "', line "
00192 << lineno << endl;
00193 else
00194 {
00195 if (dict.find(key)!=dict.end())
00196 cerr << "Warning: key '" << key << "' multiply defined in '"
00197 << filename << "', line " << lineno << endl;
00198 dict[key]=value;
00199 }
00200 }
00201 else
00202 cerr << "Warning: unrecognized format in '" << filename << "', line "
00203 << lineno << ":\n" << line << endl;
00204 }
00205 }
00206 }
00207
00208 namespace {
00209
00210 bool isParam (const string &s)
00211 {
00212 if (s.size()<2) return false;
00213 if (s[0]!='-') return false;
00214 return !(isdigit(s[1]) || (s[1]=='.'));
00215 }
00216
00217 }
00218
00219 void parse_cmdline_classic (int argc, const char **argv,
00220 const vector<string> &leading_args, map<string,string> &dict)
00221 {
00222 dict.clear();
00223 planck_assert(tsize(argc)>leading_args.size(),"not enough arguments");
00224 for (tsize i=0; i<leading_args.size(); ++i)
00225 dict[leading_args[i]] = argv[i+1];
00226 int curarg=leading_args.size()+1;
00227 while (curarg<argc)
00228 {
00229 string param=argv[curarg];
00230 planck_assert(isParam(param),"unrecognized command line format");
00231 if ((curarg==argc-1) || isParam(argv[curarg+1]))
00232 {
00233 dict[param.substr(1)]="true";
00234 ++curarg;
00235 }
00236 else
00237 {
00238 dict[param.substr(1)]=argv[curarg+1];
00239 curarg+=2;
00240 }
00241 }
00242 }
00243
00244 void parse_cmdline_classic (int argc, const char **argv,
00245 map<string,string> &dict)
00246 { parse_cmdline_classic (argc, argv, vector<string>(), dict); }
00247
00248 void parse_cmdline_equalsign (int argc, const char **argv,
00249 const vector<string> &leading_args, map<string,string> &dict)
00250 {
00251 dict.clear();
00252 planck_assert(tsize(argc)>leading_args.size(),"not enough arguments");
00253 for (tsize i=0; i<leading_args.size(); ++i)
00254 dict[leading_args[i]] = argv[i+1];
00255 for (int i=leading_args.size()+1; i<argc; ++i)
00256 {
00257 string arg=trim(argv[i]);
00258 if (arg.size()>0)
00259 {
00260 string::size_type eqpos=arg.find("=");
00261 if (eqpos!=string::npos)
00262 {
00263 string key=trim(arg.substr(0,eqpos)),
00264 value=trim(arg.substr(eqpos+1,string::npos));
00265 if (key=="")
00266 cerr << "Warning: empty key in argument'" << arg << "'" << endl;
00267 else
00268 {
00269 if (dict.find(key)!=dict.end())
00270 cerr << "Warning: key '" << key << "' multiply defined" << endl;
00271 dict[key]=value;
00272 }
00273 }
00274 else
00275 cerr << "Warning: unrecognized format in argument '" << arg << "'"
00276 << endl;
00277 }
00278 }
00279 }
00280
00281 void parse_cmdline_equalsign (int argc, const char **argv,
00282 map<string,string> &dict)
00283 { parse_cmdline_equalsign (argc, argv, vector<string>(), dict); }
00284
00285 namespace {
00286
00287 template<typename T> void split (istream &stream, vector<T> &list)
00288 {
00289 list.clear();
00290 while (stream)
00291 {
00292 string word;
00293 stream >> word;
00294 planck_assert (stream||stream.eof(),
00295 string("error while splitting stream into ") + type2typename<T>()
00296 + "components");
00297 if (stream) list.push_back(stringToData<T>(word));
00298 }
00299 }
00300
00301 }
00302
00303 template<typename T> void split (const string &inp, vector<T> &list)
00304 {
00305 istringstream stream(inp);
00306 split (stream,list);
00307 }
00308
00309 template void split (const string &inp, vector<string> &list);
00310 template void split (const string &inp, vector<float> &list);
00311 template void split (const string &inp, vector<double> &list);
00312 template void split (const string &inp, vector<int> &list);
00313 template void split (const string &inp, vector<long> &list);
00314
00315 void tokenize (const string &inp, char delim, vector<string> &list)
00316 {
00317 istringstream stream(inp);
00318 string token;
00319 list.clear();
00320 while (getline(stream,token,delim))
00321 list.push_back(token);
00322 }
00323
00324 void parse_words_from_file (const string &filename, vector<string> &words)
00325 {
00326 words.clear();
00327 ifstream inp(filename.c_str());
00328 planck_assert (inp,"Could not open file '"+filename+"'.");
00329 while (inp)
00330 {
00331 string word;
00332 inp>>word;
00333 word=trim(word);
00334 if (word!="") words.push_back(word);
00335 }
00336 }