LevelS C++ support library  3.83
string_utils.cc
1 /*
2  * This file is part of libcxxsupport.
3  *
4  * libcxxsupport is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * libcxxsupport is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with libcxxsupport; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
21  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
22  * (DLR).
23  */
24 
25 /*
26  * This file contains the implementation of various convenience functions
27  * used by the Planck LevelS package.
28  *
29  * Copyright (C) 2002-2014 Max-Planck-Society
30  * Author: Martin Reinecke
31  */
32 
33 #include <sstream>
34 #include <fstream>
35 #include <iostream>
36 #include <iomanip>
37 #include <string>
38 #include <cstring>
39 #include <cctype>
40 #include "string_utils.h"
41 
42 using namespace std;
43 
44 string trim (const string &orig)
45  {
46  string::size_type p1=orig.find_first_not_of(" \t");
47  if (p1==string::npos) return "";
48  string::size_type p2=orig.find_last_not_of(" \t");
49  return orig.substr(p1,p2-p1+1);
50  }
51 
52 template<typename T> string dataToString (const T &x)
53  {
54  ostringstream strstrm;
55  strstrm << x;
56  return trim(strstrm.str());
57  }
58 
59 template<> string dataToString (const bool &x)
60  { return x ? "T" : "F"; }
61 template<> string dataToString (const string &x)
62  { return trim(x); }
63 template<> string dataToString (const float &x)
64  {
65  ostringstream strstrm;
66  strstrm << setprecision(8) << x;
67  return trim(strstrm.str());
68  }
69 template<> string dataToString (const double &x)
70  {
71  ostringstream strstrm;
72  strstrm << setprecision(16) << x;
73  return trim(strstrm.str());
74  }
75 template<> string dataToString (const long double &x)
76  {
77  ostringstream strstrm;
78  strstrm << setprecision(25) << x;
79  return trim(strstrm.str());
80  }
81 
82 template string dataToString (const signed char &x);
83 template string dataToString (const unsigned char &x);
84 template string dataToString (const short &x);
85 template string dataToString (const unsigned short &x);
86 template string dataToString (const int &x);
87 template string dataToString (const unsigned int &x);
88 template string dataToString (const long &x);
89 template string dataToString (const unsigned long &x);
90 template string dataToString (const long long &x);
91 template string dataToString (const unsigned long long &x);
92 
93 string intToString(int64 x, tsize width)
94  {
95  ostringstream strstrm;
96  (x>=0) ? strstrm << setw(width) << setfill('0') << x
97  : strstrm << "-" << setw(width-1) << setfill('0') << -x;
98  string res = strstrm.str();
99  planck_assert(res.size()==width,"number too large");
100  return trim(res);
101  }
102 
103 namespace {
104 
105 void end_stringToData (const string &x, const char *tn, istringstream &strstrm)
106  {
107  string error = string("conversion error in stringToData<")+tn+">(\""+x+"\")";
108  planck_assert (strstrm,error);
109  string rest;
110  strstrm >> rest;
111 // rest=trim(rest);
112  planck_assert (rest.length()==0,error);
113  }
114 
115 } // unnamed namespace
116 
117 template<typename T> void stringToData (const string &x, T &value)
118  {
119  istringstream strstrm(x);
120  strstrm >> value;
121  end_stringToData (x,type2typename<T>(),strstrm);
122  }
123 
124 template<> void stringToData (const string &x, string &value)
125  { value = trim(x); }
126 
127 template<> void stringToData (const string &x, bool &value)
128  {
129  const char *fval[] = {"f","n","false",".false."};
130  const char *tval[] = {"t","y","true",".true."};
131  for (tsize i=0; i< sizeof(fval)/sizeof(fval[0]); ++i)
132  if (equal_nocase(x,fval[i])) { value=false; return; }
133  for (tsize i=0; i< sizeof(tval)/sizeof(tval[0]); ++i)
134  if (equal_nocase(x,tval[i])) { value=true; return; }
135  planck_fail("conversion error in stringToData<bool>(\""+x+"\")");
136  }
137 
138 template void stringToData (const string &x, signed char &value);
139 template void stringToData (const string &x, unsigned char &value);
140 template void stringToData (const string &x, short &value);
141 template void stringToData (const string &x, unsigned short &value);
142 template void stringToData (const string &x, int &value);
143 template void stringToData (const string &x, unsigned int &value);
144 template void stringToData (const string &x, long &value);
145 template void stringToData (const string &x, unsigned long &value);
146 template void stringToData (const string &x, long long &value);
147 template void stringToData (const string &x, unsigned long long &value);
148 template void stringToData (const string &x, float &value);
149 template void stringToData (const string &x, double &value);
150 template void stringToData (const string &x, long double &value);
151 
152 bool equal_nocase (const string &a, const string &b)
153  {
154  if (a.size()!=b.size()) return false;
155  for (tsize m=0; m<a.size(); ++m)
156  if (tolower(a[m])!=tolower(b[m])) return false;
157  return true;
158  }
159 
160 string tolower(const string &input)
161  {
162  string result=input;
163  for (tsize m=0; m<result.size(); ++m)
164  result[m]=char(tolower(result[m]));
165  return result;
166  }
167 
168 void parse_file (const string &filename, map<string,string> &dict)
169  {
170  int lineno=0;
171  dict.clear();
172  ifstream inp(filename.c_str());
173  planck_assert (inp,"Could not open parameter file '"+filename+"'.");
174  while (inp)
175  {
176  string line;
177  getline(inp, line);
178  ++lineno;
179  // remove potential carriage returns at the end of the line
180  line=line.substr(0,line.find("\r"));
181  line=line.substr(0,line.find("#"));
182  line=trim(line);
183  if (line.size()>0)
184  {
185  string::size_type eqpos=line.find("=");
186  if (eqpos!=string::npos)
187  {
188  string key=trim(line.substr(0,eqpos)),
189  value=trim(line.substr(eqpos+1,string::npos));
190  if (key=="")
191  cerr << "Warning: empty key in '" << filename << "', line "
192  << lineno << endl;
193  else
194  {
195  if (dict.find(key)!=dict.end())
196  cerr << "Warning: key '" << key << "' multiply defined in '"
197  << filename << "', line " << lineno << endl;
198  dict[key]=value;
199  }
200  }
201  else
202  cerr << "Warning: unrecognized format in '" << filename << "', line "
203  << lineno << ":\n" << line << endl;
204  }
205  }
206  }
207 
208 namespace {
209 
210 bool isParam (const string &s)
211  {
212  if (s.size()<2) return false;
213  if (s[0]!='-') return false;
214  return !(isdigit(s[1]) || (s[1]=='.'));
215  }
216 
217 } // unnamed namespace
218 
219 void parse_cmdline_classic (int argc, const char **argv,
220  const vector<string> &leading_args, map<string,string> &dict)
221  {
222  dict.clear();
223  planck_assert(tsize(argc)>leading_args.size(),"not enough arguments");
224  for (tsize i=0; i<leading_args.size(); ++i)
225  dict[leading_args[i]] = argv[i+1];
226  int curarg=leading_args.size()+1;
227  while (curarg<argc)
228  {
229  string param=argv[curarg];
230  planck_assert(isParam(param),"unrecognized command line format");
231  if ((curarg==argc-1) || isParam(argv[curarg+1]))
232  {
233  dict[param.substr(1)]="true";
234  ++curarg;
235  }
236  else
237  {
238  dict[param.substr(1)]=argv[curarg+1];
239  curarg+=2;
240  }
241  }
242  }
243 
244 void parse_cmdline_classic (int argc, const char **argv,
245  map<string,string> &dict)
246  { parse_cmdline_classic (argc, argv, vector<string>(), dict); }
247 
248 void parse_cmdline_equalsign (int argc, const char **argv,
249  const vector<string> &leading_args, map<string,string> &dict)
250  {
251  dict.clear();
252  planck_assert(tsize(argc)>leading_args.size(),"not enough arguments");
253  for (tsize i=0; i<leading_args.size(); ++i)
254  dict[leading_args[i]] = argv[i+1];
255  for (int i=leading_args.size()+1; i<argc; ++i)
256  {
257  string arg=trim(argv[i]);
258  if (arg.size()>0)
259  {
260  string::size_type eqpos=arg.find("=");
261  if (eqpos!=string::npos)
262  {
263  string key=trim(arg.substr(0,eqpos)),
264  value=trim(arg.substr(eqpos+1,string::npos));
265  if (key=="")
266  cerr << "Warning: empty key in argument'" << arg << "'" << endl;
267  else
268  {
269  if (dict.find(key)!=dict.end())
270  cerr << "Warning: key '" << key << "' multiply defined" << endl;
271  dict[key]=value;
272  }
273  }
274  else
275  cerr << "Warning: unrecognized format in argument '" << arg << "'"
276  << endl;
277  }
278  }
279  }
280 
281 void parse_cmdline_equalsign (int argc, const char **argv,
282  map<string,string> &dict)
283  { parse_cmdline_equalsign (argc, argv, vector<string>(), dict); }
284 
285 namespace {
286 
287 template<typename T> void split (istream &stream, vector<T> &list)
288  {
289  list.clear();
290  while (stream)
291  {
292  string word;
293  stream >> word;
294  planck_assert (stream||stream.eof(),
295  string("error while splitting stream into ") + type2typename<T>()
296  + "components");
297  if (stream) list.push_back(stringToData<T>(word));
298  }
299  }
300 
301 } // unnamed namespace
302 
303 template<typename T> void split (const string &inp, vector<T> &list)
304  {
305  istringstream stream(inp);
306  split (stream,list);
307  }
308 
309 template void split (const string &inp, vector<string> &list);
310 template void split (const string &inp, vector<float> &list);
311 template void split (const string &inp, vector<double> &list);
312 template void split (const string &inp, vector<int> &list);
313 template void split (const string &inp, vector<long> &list);
314 
315 void tokenize (const string &inp, char delim, vector<string> &list)
316  {
317  istringstream stream(inp);
318  string token;
319  list.clear();
320  while (getline(stream,token,delim))
321  list.push_back(token);
322  }
323 
324 void parse_words_from_file (const string &filename, vector<string> &words)
325  {
326  words.clear();
327  ifstream inp(filename.c_str());
328  planck_assert (inp,"Could not open file '"+filename+"'.");
329  while (inp)
330  {
331  string word;
332  inp>>word;
333  word=trim(word);
334  if (word!="") words.push_back(word);
335  }
336  }
void tokenize(const std::string &inp, char delim, std::vector< std::string > &list)
string intToString(int64 x, tsize width)
Definition: string_utils.cc:93
void parse_words_from_file(const std::string &filename, std::vector< std::string > &words)
std::size_t tsize
Definition: datatypes.h:116
bool equal_nocase(const std::string &a, const std::string &b)
std::string trim(const std::string &orig)
void parse_file(const std::string &filename, std::map< std::string, std::string > &dict)
void stringToData(const std::string &x, T &value)
string dataToString(const T &x)
Definition: string_utils.cc:52
#define planck_assert(testval, msg)
void split(const std::string &inp, std::vector< T > &list)
#define planck_fail(msg)
std::string tolower(const std::string &input)

Generated on Wed Nov 13 2024 12:18:16 for LevelS C++ support library