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

Last change on this file since 16936 was 16803, checked in by tbretz, 11 years ago
If the first argument does contain an equal sign consider it to be the first argument rather than the filename.
File size: 6.8 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
16#include <boost/tokenizer.hpp>
17#include <boost/algorithm/string.hpp>
18
19using namespace std;
20
21string Tools::Format(const char *fmt, va_list &ap)
22{
23 int n=256;
24
25 char *ret=0;
26 while (1)
27 {
28 ret = new char[n+1];
29
30 const int sz = vsnprintf(ret, n, fmt, ap);
31 if (sz<=n)
32 break;
33
34 n *= 2;
35 delete [] ret;
36 };
37
38 string str(ret);
39
40 delete [] ret;
41
42 return str;
43}
44
45string Tools::Form(const char *fmt, ...)
46{
47 va_list ap;
48 va_start(ap, fmt);
49
50 string str = Format(fmt, ap);
51
52 va_end(ap);
53
54 return str;
55}
56
57// --------------------------------------------------------------------------
58//
59//! This is a static helper to remove leading and trailing whitespaces.
60//!
61//! @param buf
62//! a pointer to the char array from which the whitespaces should be
63//! removed
64//!
65//! @returns
66//! a std::string with the whitespaces removed from buf
67//
68string Tools::Trim(const string &str)
69{
70 // Trim Both leading and trailing spaces
71 const size_t start = str.find_first_not_of(' '); // Find the first character position after excluding leading blank spaces
72 const size_t end = str.find_last_not_of(' '); // Find the first character position from reverse af
73
74 // if all spaces or empty return an empty string
75 if (string::npos==start || string::npos==end)
76 return string();
77
78 return str.substr(start, end-start+1);
79}
80
81// --------------------------------------------------------------------------
82//
83//! This is a static helper to remove leading and trailing whitespaces and
84//! if available leading and trailing quotes, can be either ' or "
85//!
86//! @param buf
87//! a pointer to the char array to be trimmed
88//!
89//! @returns
90//! a std::string with the content trimmed
91//
92string Tools::TrimQuotes(const string &str)
93{
94 string rc = Trim(str);
95 if (rc.length()<2)
96 return rc;
97
98 const char b = rc[0];
99 const char e = rc[rc.length()-1];
100
101 if ((b=='\"' && e=='\"') || (b=='\'' && e=='\''))
102 return rc.substr(1, rc.length()-2);
103
104 return rc;
105}
106
107// --------------------------------------------------------------------------
108//
109//! This is a static helper to remove leading and trailing whitespaces.
110//!
111//! Usage example:
112//!
113//! \code
114//! string str = " Dies ist ein test fuer einen ganz langen Satz "
115//! "und ob er korrekt umgebrochen und formatiert wird. Alles "
116//! "nur ein simpler test aber trotzdem ganz wichtig.";
117//!
118//! cout << setfill('-') << setw(40) << "+" << endl;
119//! while (1)
120//! {
121//! const string rc = Tools::Wrap(str, 40);
122//! if (rc.empty())
123//! break;
124//! cout << rc << endl;
125//! }
126//! \endcode
127//!
128string Tools::Wrap(string &str, size_t width)
129{
130 const size_t pos = str.length()<width ? string::npos : str.find_last_of(' ', width);
131 if (pos==string::npos)
132 {
133 const string rc = str;
134 str = "";
135 return rc;
136 }
137
138 const size_t indent = str.find_first_not_of(' ');
139
140 const string rc = str.substr(0, pos);
141 const size_t p2 = str.find_first_not_of(' ', pos+1);
142
143 str = str.substr(0, indent) + str.substr(p2==string::npos ? pos+1 : p2);
144
145 return rc;
146}
147
148string Tools::Scientific(uint64_t val)
149{
150 ostringstream rc;
151 rc << setprecision(1) << fixed;
152
153 if (val<1000)
154 {
155 rc << val << " ";
156 return rc.str();
157 }
158
159 if (val<3000)
160 {
161 rc << val/1000. << " k";
162 return rc.str();
163 }
164
165 if (val<1000000)
166 {
167 rc << val/1000 << " k";
168 return rc.str();
169 }
170
171 if (val<3000000)
172 {
173 rc << val/1000000. << " M";
174 return rc.str();
175 }
176
177 if (val<1000000000)
178 {
179 rc << val/1000000 << " M";
180 return rc.str();
181 }
182
183 if (val<3000000000)
184 {
185 rc << val/1000000000. << " G";
186 return rc.str();
187 }
188
189 if (val<1000000000000)
190 {
191 rc << val/1000000000 << " G";
192 return rc.str();
193 }
194
195 if (val<3000000000000)
196 {
197 rc << val/1000000000000. << " T";
198 return rc.str();
199 }
200
201 if (val<1000000000000000)
202 {
203 rc << val/1000000000000 << " T";
204 return rc.str();
205 }
206
207 if (val<3000000000000000)
208 {
209 rc << val/1000000000000000. << " P";
210 return rc.str();
211 }
212
213 rc << val/1000000000000000. << " P";
214 return rc.str();
215}
216
217// --------------------------------------------------------------------------
218//
219//! Splits a string into a filename and command line arguments, like:
220//!
221//! file.txt arg1=argument1 arg2="argument 2" arg3="argument \"3\""
222//!
223//! 'file.txt' will be returned on opt, the arguments will be returned in
224//! the returned map.
225//!
226//! If the returned file name is empty, an error has occured:
227//! If the map is also empty the file name was empty, if the map has
228//! one entry then for this entry the equal sign was missing.
229//!
230map<string,string> Tools::Split(string &opt, bool allow)
231{
232 using namespace boost;
233 typedef escaped_list_separator<char> separator;
234
235 const string data(opt);
236
237 const tokenizer<separator> tok(data, separator("\\", " ", "\"'"));
238
239 auto it=tok.begin();
240 if (it==tok.end())
241 {
242 opt = "";
243 return map<string,string>();
244 }
245
246 opt = string(*it).find_first_of('=')==string::npos ? *it++ : "";
247
248 map<string,string> rc;
249
250 int i=-1;
251
252 for (; it!=tok.end(); it++)
253 {
254 if (it->empty())
255 continue;
256
257 i++;
258
259 const size_t pos = it->find_first_of('=');
260 if (pos==string::npos)
261 {
262 if (allow)
263 {
264 rc[to_string(i)] = *it;
265 continue;
266 }
267
268 opt = "";
269 rc.clear();
270 rc[*it] = "";
271 return rc;
272 }
273
274 rc[it->substr(0, pos)] = it->substr(pos+1);
275 }
276
277 return rc;
278}
279
280vector<string> Tools::Split(const string &str, const string &delim)
281{
282 vector<string> rc;
283 boost::split(rc, str, boost::is_any_of(delim));
284 return rc;
285}
286
287// --------------------------------------------------------------------------
288//
289//! Returns the string with a comment (introduced by a #) stripped. The
290//! comment mark can be escaped by either \# or "#"
291//!
292string Tools::Uncomment(const string &opt)
293{
294 using namespace boost;
295 typedef escaped_list_separator<char> separator;
296
297 const auto it = tokenizer<separator>(opt, separator("\\", "#", "\"'")).begin();
298
299 const int charPos = it.base() - opt.begin();
300
301 return charPos<1 ? "" : opt.substr(0, opt[charPos-1]=='#' ? charPos-1 : charPos);
302}
Note: See TracBrowser for help on using the repository browser.