wibble  1.1
string.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 #ifndef WIBBLE_STRING_H
3 #define WIBBLE_STRING_H
4 
5 /*
6  * Various string functions
7  *
8  * Copyright (C) 2007,2008 Enrico Zini <enrico@debian.org>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  */
24 
25 #include <wibble/operators.h>
26 #include <wibble/sfinae.h>
27 
28 #include <cstdarg>
29 #include <cstdio>
30 #include <string>
31 #include <set>
32 #include <vector>
33 #include <deque>
34 #include <sstream>
35 #include <cctype>
36 #ifdef _WIN32
37 #include <cstring>
38 #include <cstdlib>
39 #endif
40 
41 namespace wibble {
42 namespace str {
43 
44 using namespace wibble::operators;
45 
46 #ifdef _WIN32
47 static int vasprintf (char **, const char *, va_list);
48 #endif
49 
50 std::string fmtf( const char* f, ... );
51 template< typename T > inline std::string fmt(const T& val);
52 
53 // Formatting lists -- actually, we need to move list handling into wibble,
54 // really.
55 template< typename X >
57  std::ostream &o, X list )
58 {
59  if ( list.empty() )
60  return o << "[]";
61 
62  o << "[ ";
63  while( !list.empty() ) {
64  o << fmt( list.head() );
65  if ( !list.tail().empty() )
66  o << ", ";
67  list = list.tail();
68  }
69  return o << " ]";
70 }
71 
73 template< typename T >
74 inline std::string fmt(const T& val)
75 {
76  std::stringstream str;
77  str << val;
78  return str.str();
79 }
80 
81 template<> inline std::string fmt<std::string>(const std::string& val) {
82  return val;
83 }
84 template<> inline std::string fmt<char*>(char * const & val) { return val; }
85 
86 template< typename C >
87 inline std::string fmt_container( const C &c, char f, char l )
88 {
89  std::string s;
90  s += f;
91  if ( c.empty() )
92  return s + l;
93 
94  s += ' ';
95  for ( typename C::const_iterator i = c.begin(); i != c.end(); ++i ) {
96  s += fmt( *i );
97  if ( i != c.end() && i + 1 != c.end() )
98  s += ", ";
99  }
100  s += ' ';
101  s += l;
102  return s;
103 }
104 
105 // formatting sets using { ... } notation
106 template< typename X >
107 inline std::string fmt(const std::set< X >& val) {
108  return fmt_container( val, '{', '}' );
109 }
110 
111 // formatting vectors using [ ... ] notation
112 template< typename X >
113 inline std::string fmt(const std::vector< X > &val) {
114  return fmt_container( val, '[', ']' );
115 }
116 
117 // formatting vectors using [ ... ] notation
118 template< typename X >
119 inline std::string fmt(const std::deque< X > &val) {
120  return fmt_container( val, '[', ']' );
121 }
122 
124 inline std::string basename(const std::string& pathname)
125 {
126  size_t pos = pathname.rfind("/");
127  if (pos == std::string::npos)
128  return pathname;
129  else
130  return pathname.substr(pos+1);
131 }
132 
134 inline std::string dirname(const std::string& pathname)
135 {
136  size_t pos = pathname.rfind("/");
137  if (pos == std::string::npos)
138  return std::string();
139  else if (pos == 0)
140  // Handle the case of '/foo'
141  return std::string("/");
142  else
143  return pathname.substr(0, pos);
144 }
145 
151 std::string normpath(const std::string& pathname);
152 
154 inline bool startsWith(const std::string& str, const std::string& part)
155 {
156  if (str.size() < part.size())
157  return false;
158  return str.substr(0, part.size()) == part;
159 }
160 
162 inline bool endsWith(const std::string& str, const std::string& part)
163 {
164  if (str.size() < part.size())
165  return false;
166  return str.substr(str.size() - part.size()) == part;
167 }
168 
169 inline std::string replace(const std::string& str, char from, char to)
170 {
171  std::string res;
172  res.reserve(str.size());
173  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
174  if (*i == from)
175  res.append(1, to);
176  else
177  res.append(1, *i);
178  return res;
179 }
180 
181 #if !__xlC__ && (! __GNUC__ || __GNUC__ >= 4)
182 
186 template<typename FUN>
187 inline std::string trim(const std::string& str, const FUN& classifier)
188 {
189  if (str.empty())
190  return str;
191 
192  size_t beg = 0;
193  size_t end = str.size() - 1;
194  while (beg < end && classifier(str[beg]))
195  ++beg;
196  while (end >= beg && classifier(str[end]))
197  --end;
198 
199  return str.substr(beg, end-beg+1);
200 }
201 
205 inline std::string trim(const std::string& str)
206 {
207  return trim(str, ::isspace);
208 }
209 #else
210 inline std::string trim(const std::string& str)
212 {
213  if (str.empty())
214  return str;
215 
216  size_t beg = 0;
217  size_t end = str.size() - 1;
218  while (beg < end && ::isspace(str[beg]))
219  ++beg;
220  while (end >= beg && ::isspace(str[end]))
221  --end;
222 
223  return str.substr(beg, end-beg+1);
224 }
225 #endif
226 
228 inline std::string toupper(const std::string& str)
229 {
230  std::string res;
231  res.reserve(str.size());
232  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
233  res += ::toupper(*i);
234  return res;
235 }
236 
238 inline std::string tolower(const std::string& str)
239 {
240  std::string res;
241  res.reserve(str.size());
242  for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
243  res += ::tolower(*i);
244  return res;
245 }
246 
248 inline std::string ucfirst(const std::string& str)
249 {
250  if (str.empty()) return str;
251  std::string res;
252  res += ::toupper(str[0]);
253  return res + tolower(str.substr(1));
254 }
255 
257 inline std::string joinpath(const std::string& path1, const std::string& path2)
258 {
259  if (path1.empty())
260  return path2;
261  if (path2.empty())
262  return path1;
263 
264  if (path1[path1.size() - 1] == '/')
265  if (path2[0] == '/')
266  return path1 + path2.substr(1);
267  else
268  return path1 + path2;
269  else
270  if (path2[0] == '/')
271  return path1 + path2;
272  else
273  return path1 + '/' + path2;
274 }
275 
276 // append path2 to path1 if path2 is not absolute, otherwise return path2
277 inline std::string appendpath( const std::string &path1, const std::string &path2 ) {
278 #ifdef POSIX
279  if ( path2.size() >= 1 && path2[ 0 ] == '/' )
280  return path2;
281 #endif
282 #ifdef WIN32
283  if ( ( path2.size() >= 3 && path2[ 1 ] == ':' && path2[ 2 ] == '\\' )
284  || ( path2.size() >= 2 && path2[ 0 ] == '\\' && path2[ 1 ] == '\\' ) )
285  return path2;
286 #endif
287  return joinpath( path1, path2 );
288 }
289 
291 std::string urlencode(const std::string& str);
292 
294 std::string urldecode(const std::string& str);
295 
297 std::string encodeBase64(const std::string& str);
298 
300 std::string decodeBase64(const std::string& str);
301 
314 class Split
315 {
316  std::string sep;
317  std::string str;
318 
319 public:
320  // TODO: add iterator_traits
322  {
323  const std::string& sep;
324  const std::string& str;
325  std::string cur;
326  size_t pos;
327 
328  public:
329  const_iterator(const std::string& sep, const std::string& str) : sep(sep), str(str), pos(0)
330  {
331  ++*this;
332  }
333  const_iterator(const std::string& sep, const std::string& str, bool) : sep(sep), str(str), pos(std::string::npos) {}
334 
336  {
337  if (pos == str.size())
338  pos = std::string::npos;
339  else
340  {
341  size_t end;
342  if (sep.empty())
343  if (pos + 1 == str.size())
344  end = std::string::npos;
345  else
346  end = pos + 1;
347  else
348  end = str.find(sep, pos);
349  if (end == std::string::npos)
350  {
351  cur = str.substr(pos);
352  pos = str.size();
353  }
354  else
355  {
356  cur = str.substr(pos, end-pos);
357  pos = end + sep.size();
358  }
359  }
360  return *this;
361  }
362 
363  std::string remainder() const
364  {
365  if (pos == std::string::npos)
366  return std::string();
367  else
368  return str.substr(pos);
369  }
370 
371  const std::string& operator*() const
372  {
373  return cur;
374  }
375  const std::string* operator->() const
376  {
377  return &cur;
378  }
379  bool operator==(const const_iterator& ti) const
380  {
381  // Comparing iterators on different strings is not supported for
382  // performance reasons
383  return pos == ti.pos;
384  }
385  bool operator!=(const const_iterator& ti) const
386  {
387  // Comparing iterators on different strings is not supported for
388  // performance reasons
389  return pos != ti.pos;
390  }
391  };
392 
396  Split(const std::string& sep, const std::string& str) : sep(sep), str(str) {}
397 
401  const_iterator begin() const { return const_iterator(sep, str); }
402  const_iterator end() const { return const_iterator(sep, str, false); }
403 };
404 
405 template<typename ITER>
406 std::string join(const ITER& begin, const ITER& end, const std::string& sep = ", ")
407 {
408  std::stringstream res;
409  bool first = true;
410  for (ITER i = begin; i != end; ++i)
411  {
412  if (first)
413  first = false;
414  else
415  res << sep;
416  res << *i;
417  }
418  return res.str();
419 }
420 
436 {
437 public:
438  // TODO: add iterator_traits
440  {
441  std::istream* in;
442  std::pair<std::string, std::string> value;
443  std::string line;
444 
445  public:
446  const_iterator(std::istream& in);
447  const_iterator() : in(0) {}
448 
449  const_iterator& operator++();
450 
451  const std::pair<std::string, std::string>& operator*() const
452  {
453  return value;
454  }
455  const std::pair<std::string, std::string>* operator->() const
456  {
457  return &value;
458  }
459  bool operator==(const const_iterator& ti) const
460  {
461  return in == ti.in;
462  }
463  bool operator!=(const const_iterator& ti) const
464  {
465  return in != ti.in;
466  }
467  };
468 
469  const_iterator begin(std::istream& in) { return const_iterator(in); }
471 };
472 
476 std::string c_escape(const std::string& str);
477 
485 std::string c_unescape(const std::string& str, size_t& lenParsed);
486 
487 
488 }
489 }
490 
491 // vim:set ts=4 sw=4:
492 #endif
bool operator==(const const_iterator &ti) const
Definition: string.h:379
std::string joinpath(const std::string &path1, const std::string &path2)
Join two paths, adding slashes when appropriate.
Definition: string.h:257
std::string c_escape(const std::string &str)
Escape the string so it can safely used as a C string inside double quotes.
Definition: string.cpp:400
std::string toupper(const std::string &str)
Convert a string to uppercase.
Definition: string.h:228
const std::string * operator->() const
Definition: string.h:375
const std::string & operator*() const
Definition: string.h:371
bool operator!=(const const_iterator &ti) const
Definition: string.h:385
std::string appendpath(const std::string &path1, const std::string &path2)
Definition: string.h:277
const_iterator end()
Definition: string.h:470
const_iterator begin() const
Split the string and iterate the resulting tokens.
Definition: string.h:401
Split a string where a given substring is found.
Definition: string.h:314
A First
Definition: sfinae.h:97
ListIterator< List > begin(List l)
Definition: list.h:420
const std::pair< std::string, std::string > & operator*() const
Definition: string.h:451
const_iterator begin(std::istream &in)
Definition: string.h:469
Definition: operators.h:12
std::string urldecode(const std::string &str)
Decode an urlencoded string.
Definition: string.cpp:178
std::string fmt(const char *f,...)
Definition: string.cpp:123
std::string basename(const std::string &pathname)
Given a pathname, return the file name without its path.
Definition: string.h:124
std::string encodeBase64(const std::string &str)
Encode a string in Base64.
Definition: string.cpp:208
std::string replace(const std::string &str, char from, char to)
Definition: string.h:169
TPair< std::ostream, typename X::Type >::First & operator<<(std::ostream &o, X list)
Definition: string.h:56
const_iterator()
Definition: string.h:447
bool operator!=(const const_iterator &ti) const
Definition: string.h:463
const_iterator & operator++()
Definition: string.h:335
const_iterator(const std::string &sep, const std::string &str)
Definition: string.h:329
const std::pair< std::string, std::string > * operator->() const
Definition: string.h:455
Parse a record of Yaml-style field: value couples.
Definition: string.h:435
std::string normpath(const std::string &pathname)
Normalise a pathname.
Definition: string.cpp:133
Definition: string.h:321
bool operator==(const const_iterator &ti) const
Definition: string.h:459
std::string ucfirst(const std::string &str)
Return the same string, with the first character uppercased.
Definition: string.h:248
Definition: amorph.h:17
bool endsWith(const std::string &str, const std::string &part)
Check if a string ends with the given substring.
Definition: string.h:162
Split(const std::string &sep, const std::string &str)
Create a splitter that uses the given regular expression to find tokens.
Definition: string.h:396
bool startsWith(const std::string &str, const std::string &part)
Check if a string starts with the given substring.
Definition: string.h:154
std::string dirname(const std::string &pathname)
Given a pathname, return the directory name without the file name.
Definition: string.h:134
std::string trim(const std::string &str, const FUN &classifier)
Return the substring of &#39;str&#39; without all leading and trailing characters for which &#39;classifier&#39; retu...
Definition: string.h:187
std::string tolower(const std::string &str)
Convert a string to lowercase.
Definition: string.h:238
std::string decodeBase64(const std::string &str)
Decode a string encoded in Base64.
Definition: string.cpp:241
std::string urlencode(const std::string &str)
Urlencode a string.
Definition: string.cpp:160
std::string fmt_container(const C &c, char f, char l)
Definition: string.h:87
const_iterator(const std::string &sep, const std::string &str, bool)
Definition: string.h:333
std::string c_unescape(const std::string &str, size_t &lenParsed)
Unescape a C string, stopping at the first double quotes or at the end of the string.
Definition: string.cpp:424
std::string remainder() const
Definition: string.h:363
ListIterator< List > end(List)
Definition: list.h:425
const_iterator end() const
Definition: string.h:402
std::string fmtf(const char *f,...)
Definition: string.cpp:113
std::string join(const ITER &begin, const ITER &end, const std::string &sep=", ")
Definition: string.h:406