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

Last change on this file was 19211, checked in by tbretz, 2 years ago
Fixed a typo in the pre-processor directive
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.