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

Last change on this file since 16329 was 15167, checked in by tbretz, 12 years ago
Added Split(), a wrapper around boost::split
File size: 6.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
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 = *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.