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