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

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