source: trunk/FACT++/src/tools.cc@ 19183

Last change on this file since 19183 was 19179, checked in by tbretz, 6 years ago
Secured against clang <= 4
File size: 9.1 KB
Line 
1// **************************************************************************
2/** @file tools.cc
3
4@todo
5 - Resolve the dependancies with dim
6 - Move code to a more appropriate place
7 - put stuff in namespaces
8*/
9// **************************************************************************
10#include "tools.h"
11
12#include <stdarg.h>
13#include <math.h>
14
15#include <iomanip>
16#include <sstream>
17#include <math.h>
18
19#include <boost/tokenizer.hpp>
20#include <boost/algorithm/string.hpp>
21
22using namespace std;
23
24string Tools::Format(const char *fmt, va_list &ap)
25{
26 int n=256;
27
28 char *ret=0;
29 while (1)
30 {
31 ret = new char[n+1];
32
33 const int sz = vsnprintf(ret, n, fmt, ap);
34 if (sz<=n)
35 break;
36
37 n *= 2;
38 delete [] ret;
39 };
40
41 string str(ret);
42
43 delete [] ret;
44
45 return str;
46}
47
48string Tools::Form(const char *fmt, ...)
49{
50 va_list ap;
51 va_start(ap, fmt);
52
53 string str = Format(fmt, ap);
54
55 va_end(ap);
56
57 return str;
58}
59
60// --------------------------------------------------------------------------
61//
62//! This is a static helper to remove leading and trailing whitespaces.
63//!
64//! @param buf
65//! a pointer to the char array from which the whitespaces should be
66//! removed
67//!
68//! @returns
69//! a std::string with the whitespaces removed from buf
70//
71string Tools::Trim(const string &str)
72{
73 // Trim Both leading and trailing spaces
74 const size_t start = str.find_first_not_of(' '); // Find the first character position after excluding leading blank spaces
75 const size_t end = str.find_last_not_of(' '); // Find the first character position from reverse af
76
77 // if all spaces or empty return an empty string
78 if (string::npos==start || string::npos==end)
79 return string();
80
81 return str.substr(start, end-start+1);
82}
83
84// --------------------------------------------------------------------------
85//
86//! This is a static helper to remove leading and trailing whitespaces and
87//! if available leading and trailing quotes, can be either ' or "
88//!
89//! @param buf
90//! a pointer to the char array to be trimmed
91//!
92//! @returns
93//! a std::string with the content trimmed
94//
95string Tools::TrimQuotes(const string &str)
96{
97 string rc = Trim(str);
98 if (rc.length()<2)
99 return rc;
100
101 const char b = rc[0];
102 const char e = rc[rc.length()-1];
103
104 if ((b=='\"' && e=='\"') || (b=='\'' && e=='\''))
105 return rc.substr(1, rc.length()-2);
106
107 return rc;
108}
109
110// --------------------------------------------------------------------------
111//
112//! This is a static helper to remove leading and trailing whitespaces.
113//!
114//! Usage example:
115//!
116//! \code
117//! string str = " Dies ist ein test fuer einen ganz langen Satz "
118//! "und ob er korrekt umgebrochen und formatiert wird. Alles "
119//! "nur ein simpler test aber trotzdem ganz wichtig.";
120//!
121//! cout << setfill('-') << setw(40) << "+" << endl;
122//! while (1)
123//! {
124//! const string rc = Tools::Wrap(str, 40);
125//! if (rc.empty())
126//! break;
127//! cout << rc << endl;
128//! }
129//! \endcode
130//!
131string Tools::Wrap(string &str, size_t width)
132{
133 const size_t pos = str.length()<width ? string::npos : str.find_last_of(' ', width);
134 if (pos==string::npos)
135 {
136 const string rc = str;
137 str = "";
138 return rc;
139 }
140
141 const size_t indent = str.find_first_not_of(' ');
142
143 const string rc = str.substr(0, pos);
144 const size_t p2 = str.find_first_not_of(' ', pos+1);
145
146 str = str.substr(0, indent) + str.substr(p2==string::npos ? pos+1 : p2);
147
148 return rc;
149}
150
151string Tools::Scientific(uint64_t val)
152{
153 ostringstream rc;
154 rc << setprecision(1) << fixed;
155
156 if (val<1000)
157 {
158 rc << val << " ";
159 return rc.str();
160 }
161
162 if (val<3000)
163 {
164 rc << val/1000. << " k";
165 return rc.str();
166 }
167
168 if (val<1000000)
169 {
170 rc << val/1000 << " k";
171 return rc.str();
172 }
173
174 if (val<3000000)
175 {
176 rc << val/1000000. << " M";
177 return rc.str();
178 }
179
180 if (val<1000000000)
181 {
182 rc << val/1000000 << " M";
183 return rc.str();
184 }
185
186 if (val<3000000000)
187 {
188 rc << val/1000000000. << " G";
189 return rc.str();
190 }
191
192 if (val<1000000000000)
193 {
194 rc << val/1000000000 << " G";
195 return rc.str();
196 }
197
198 if (val<3000000000000)
199 {
200 rc << val/1000000000000. << " T";
201 return rc.str();
202 }
203
204 if (val<1000000000000000)
205 {
206 rc << val/1000000000000 << " T";
207 return rc.str();
208 }
209
210 if (val<3000000000000000)
211 {
212 rc << val/1000000000000000. << " P";
213 return rc.str();
214 }
215
216 rc << val/1000000000000000. << " P";
217 return rc.str();
218}
219
220string Tools::Fractional(const double &val)
221{
222 ostringstream rc;
223 rc << setprecision(1) << fixed;
224
225 const auto abs = fabs(val);
226
227 if (abs>1)
228 {
229 rc << val << " ";
230 return rc.str();
231 }
232
233 if (abs>1e-3)
234 {
235 rc << val*1000 << " m";
236 return rc.str();
237 }
238
239 if (abs>1e-6)
240 {
241 rc << val*1000000 << " u";
242 return rc.str();
243 }
244
245 if (abs>1e-9)
246 {
247 rc << val*1000000000 << " n";
248 return rc.str();
249 }
250
251 if (abs>1e-12)
252 {
253 rc << val*1000000000000. << " p";
254 return rc.str();
255 }
256
257 rc << abs*1000000000000000. << " f";
258 return rc.str();
259}
260
261// --------------------------------------------------------------------------
262//
263//! Splits a string into a filename and command line arguments, like:
264//!
265//! file.txt arg1=argument1 arg2="argument 2" arg3="argument \"3\""
266//!
267//! 'file.txt' will be returned on opt, the arguments will be returned in
268//! the returned map.
269//!
270//! If the returned file name is empty, an error has occured:
271//! If the map is also empty the file name was empty, if the map has
272//! one entry then for this entry the equal sign was missing.
273//
274//! allow==true allows for positional (empty) arguments, like in
275//! file.txt arg1 arg2="argument 2" arg3
276//!
277map<string,string> Tools::Split(string &opt, bool allow)
278{
279 using namespace boost;
280 typedef escaped_list_separator<char> separator;
281
282 const string data(opt);
283
284 const tokenizer<separator> tok(data, separator("\\", " ", "\"'"));
285
286 auto it=tok.begin();
287 if (it==tok.end())
288 {
289 opt = "";
290 return map<string,string>();
291 }
292
293 opt = string(*it).find_first_of('=')==string::npos ? *it++ : "";
294
295 map<string,string> rc;
296
297 int cnt=0;
298
299 for (; it!=tok.end(); it++)
300 {
301 if (it->empty())
302 continue;
303
304 const size_t pos = it->find_first_of('=');
305 if (pos==string::npos)
306 {
307 if (allow)
308 {
309 rc[to_string(cnt++)] = *it;
310 continue;
311 }
312
313 opt = "";
314 rc.clear();
315 rc[*it] = "";
316 return rc;
317 }
318
319 rc[it->substr(0, pos)] = it->substr(pos+1);
320 }
321
322 return rc;
323}
324
325vector<string> Tools::Split(const string &str, const string &delim)
326{
327 vector<string> rc;
328 boost::split(rc, str, boost::is_any_of(delim));
329 return rc;
330}
331
332// --------------------------------------------------------------------------
333//
334//! Returns the string with a comment (introduced by a #) stripped. The
335//! comment mark can be escaped by either \# or "#"
336//!
337string Tools::Uncomment(const string &opt)
338{
339 using namespace boost;
340 typedef escaped_list_separator<char> separator;
341
342 const auto it = tokenizer<separator>(opt, separator("\\", "#", "\"'")).begin();
343
344 const int charPos = it.base() - opt.begin();
345
346 return charPos<1 ? "" : opt.substr(0, opt[charPos-1]=='#' ? charPos-1 : charPos);
347}
348
349// --------------------------------------------------------------------------
350//
351//! Wraps a given text into a vector of strings with not more than
352//! max size lines
353//!
354vector<string> Tools::WordWrap(string text, const uint16_t &max)
355{
356 if (text.size()<max)
357 return { text };
358
359 vector<string> rc;
360 while (1)
361 {
362 // Remove trailing white spaces
363 const size_t st = text.find_first_not_of(' ');
364 if (st==string::npos)
365 break;
366
367 text.erase(0, st);
368 if (text.size()<max)
369 {
370 rc.push_back(text);
371 break;
372 }
373
374 // Last white space - position to break
375 const size_t ws = text.find_last_of(' ', max);
376 if (ws==string::npos)
377 {
378 rc.push_back(text.substr(0, max));
379 text.erase(0, max);
380 continue;
381 }
382
383 // Previous non-whitespace, last position to keep
384 const size_t ch = text.find_last_not_of(' ', ws);
385 if (ch==string::npos) // found only white spaces
386 continue;
387
388 rc.push_back(text.substr(0, ch+1));
389 text.erase(0, ws);
390 }
391
392 return rc;
393}
394
395#if !defined(__clang_major__) && defined(__GNUC__) && (__GNUC___ <= 4)
396
397namespace std
398{
399 string to_string(const size_t &val)
400 {
401 return to_string((long long unsigned int)val);
402 }
403
404 string to_string(const int &val)
405 {
406 return to_string((long long int)val);
407 }
408
409 string to_string(const unsigned int &val)
410 {
411 return to_string((long long int)val);
412 }
413}
414#endif
Note: See TracBrowser for help on using the repository browser.