1 // src/utils.cc
2 // This file is part of libpbe; see http://decimail.org
3 // (C) 2004-2007 Philip Endecott
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 #include "utils.hh"
20
21 #include "Exception.hh"
22
23 #if 0
24 #include <netinet/in.h>
25 #include <sstream>
26 #endif
27
28 #include <boost/lexical_cast.hpp>
29 #include <boost/algorithm/string/replace.hpp>
30 #include <boost/algorithm/string/classification.hpp>
31
32 using namespace std;
33
34
35 namespace pbe {
36
37 #if 0
38 string int_to_string(int i)
39 {
40 ostringstream s;
41 s << i;
42 return s.str();
43 }
44
45 string float_to_string(float f)
46 {
47 char buf[20];
48 unsigned int nchars = snprintf(buf,sizeof(buf),"%g",f);
49 if (nchars>=sizeof(buf)) {
50 throw "float doesn't fit in buffer";
51 }
52 return buf;
53 }
54
55 string double_to_string(double f)
56 {
57 char buf[20];
58 unsigned int nchars = snprintf(buf,sizeof(buf),"%g",f);
59 if (nchars>=sizeof(buf)) {
60 throw "float doesn't fit in buffer";
61 }
62 return buf;
63 }
64 #endif
65
66 class NotANumber: public Exception {
67 private:
68 string numstr;
69 string base;
70 public:
NotANumber(string ns,string b)71 NotANumber(string ns, string b): numstr(ns), base(b) {}
report(ostream & s) const72 void report(ostream& s) const {
73 s << '"' << numstr << "\" is not a " << base << " number" << endl;
74 }
75 };
76
77
78 #if 0
79 int string_to_int(string s)
80 {
81 if (s.size()==0) {
82 throw NotANumber(s,"decimal");
83 }
84 char* endptr;
85 int i=strtol(s.c_str(),&endptr,10);
86 if (*endptr) {
87 throw NotANumber(s,"decimal");
88 }
89 return i;
90 }
91
92
93 float string_to_float(string s)
94 {
95 if (s.size()==0) {
96 throw NotANumber(s,"floating point");
97 }
98 char* endptr;
99 float f=strtof(s.c_str(),&endptr);
100 if (*endptr) {
101 throw NotANumber(s,"floating point");
102 }
103 return f;
104 }
105
106
107 double string_to_double(string s)
108 {
109 if (s.size()==0) {
110 throw NotANumber(s,"floating point");
111 }
112 char* endptr;
113 double d=strtod(s.c_str(),&endptr);
114 if (*endptr) {
115 throw NotANumber(s,"floating point");
116 }
117 return d;
118 }
119 #endif
120
hex_string_to_int(string s)121 int hex_string_to_int(string s)
122 {
123 if (s.size()==0) {
124 throw NotANumber(s,"hex");
125 }
126 char* endptr;
127 int i=strtol(s.c_str(),&endptr,16);
128 if (*endptr) {
129 throw NotANumber(s,"hex");
130 }
131 return i;
132 }
133
134
maybe_hex_string_to_int(string s)135 int maybe_hex_string_to_int(string s)
136 {
137 if (s.substr(0,2)=="0x") {
138 return hex_string_to_int(s.substr(2));
139 } else {
140 return boost::lexical_cast<int>(s);
141 }
142 }
143
144
145 static string
prefix_backslash(const boost::iterator_range<std::string::const_iterator> & Match)146 prefix_backslash(const boost::iterator_range<std::string::const_iterator>& Match )
147 {
148 return "\\"+string(Match.begin(),Match.end());
149 }
150
151
escape_for_dquoted_string(string s)152 string escape_for_dquoted_string(string s)
153 {
154 return boost::find_format_all_copy(s,
155 boost::token_finder(boost::is_any_of("\\\"")),
156 prefix_backslash);
157 }
158
escape_for_squoted_string(string s)159 string escape_for_squoted_string(string s)
160 {
161 return boost::find_format_all_copy(s,
162 boost::token_finder(boost::is_any_of("\\\'")),
163 prefix_backslash);
164 }
165
escape_for_regexp(string s)166 string escape_for_regexp(string s)
167 {
168 return boost::find_format_all_copy(s,
169 boost::token_finder(boost::is_any_of("/*+?{().^$\\[")),
170 prefix_backslash);
171 }
172
173
174 #if 0
175 class EscapeForQuotedString: public EscapeInserter {
176 public:
177 EscapeForQuotedString(void): EscapeInserter("\\\"") {}
178 };
179
180
181
182 class EscapeForSQuotedString: public EscapeInserter {
183 public:
184 EscapeForSQuotedString(void): EscapeInserter("\\\'") {}
185 };
186
187
188
189 class EscapeForRegexp: public EscapeInserter {
190 public:
191 EscapeForRegexp(void): EscapeInserter("/*+?{().^$\\[") {}
192 };
193
194 const StringTransformer& escape_for_regexp = EscapeForRegexp();
195
196
197 class ReplaceSquoteWithHack: public StringTransformer {
198 public:
199 ReplaceSquoteWithHack(void) {
200 add_cs_rule('\'',"',\"'\",'");
201 }
202 };
203
204 string escape_for_xpath_string(string s)
205 {
206 if (s.find('\'')==s.npos) {
207 return "\'"+s+"\'";
208 }
209 if (s.find('\"')==s.npos) {
210 return "\""+s+"\"";
211 }
212 {
213 static ReplaceSquoteWithHack replace_squote_with_hack;
214 return "concat('" + replace_squote_with_hack(s) + "')";
215 }
216 }
217
218
219
220 class ToUpper: public StringTransformer {
221 public:
222 ToUpper(void) {
223 for(int c=0; c<256; ++c) {
224 add_cc_rule(c,toupper(c));
225 }
226 }
227 };
228
229 const StringTransformer& to_upper = ToUpper();
230
231
232 class ToLower: public StringTransformer {
233 public:
234 ToLower(void) {
235 for(int c=0; c<256; ++c) {
236 add_cc_rule(c,tolower(c));
237 }
238 }
239 };
240
241 const StringTransformer& to_lower = ToLower();
242
243
244 class LfToCrlf: public StringTransformer {
245 public:
246 LfToCrlf(void) {
247 add_cs_rule('\n',"\r\n");
248 }
249 };
250
251 const StringTransformer& lf_to_crlf = LfToCrlf();
252
253
254 string join(const list<string>& strs, string joiner)
255 {
256 if (strs.size()==0) {
257 return "";
258 }
259 string j;
260 list<string>::const_iterator i=strs.begin();
261 while(1) {
262 j+=(*i);
263 ++i;
264 if (i==strs.end()) {
265 break;
266 } else {
267 j+=joiner;
268 }
269 }
270 return j;
271 }
272
273
274 string trim_whitespace (string s)
275 {
276 string::size_type start = s.find_first_not_of("\r\n \t");
277 if (start==s.npos) {
278 return "";
279 }
280 unsigned int end = s.find_last_not_of("\r\n \t");
281 return s.substr(start,(end-start)+1);
282 }
283
284
285 string normalise_whitespace (string s)
286 {
287 string r;
288 bool skip_spaces=true;
289 bool add_space=false;
290
291 for(unsigned int i = 0; i<s.length(); ++i) {
292 char c = s[i];
293 if (c==' ' || c=='\t' || c=='\r' || c=='\n') {
294 if (skip_spaces) {
295 } else {
296 skip_spaces=true;
297 add_space=true;
298 }
299 } else {
300 if (add_space) {
301 r.append(1,' ');
302 add_space=false;
303 }
304 r.append(1,c);
305 skip_spaces=false;
306 }
307 }
308 return r;
309 }
310
311
312 bool starts_with ( string s, string prefix )
313 {
314 return s.substr(0,prefix.length())==prefix;
315 }
316
317
318 void check_alphanumeric ( string s )
319 {
320 string::size_type p = s.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
321 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
322 "0123456789_");
323 if (p!=s.npos) {
324 throw "Not alphanumeric";
325 }
326 }
327
328
329 void check_numeric ( string s )
330 {
331 string::size_type p = s.find_first_not_of("0123456789");
332 if (p!=s.npos) {
333 throw "Not numeric";
334 }
335 }
336 #endif
337
338 };
339
340