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

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