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
41namespace wibble {
42namespace str {
43
44using namespace wibble::operators;
45
46#ifdef _WIN32
47static int vasprintf (char **, const char *, va_list);
48#endif
49
50std::string fmtf( const char* f, ... );
51template< typename T > inline std::string fmt(const T& val);
52
53// Formatting lists -- actually, we need to move list handling into wibble,
54// really.
55template< 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
73template< typename T >
74inline std::string fmt(const T& val)
75{
76 std::stringstream str;
77 str << val;
78 return str.str();
79}
80
81template<> inline std::string fmt<std::string>(const std::string& val) {
82 return val;
83}
84template<> inline std::string fmt<char*>(char * const & val) { return val; }
85
86template< typename C >
87inline 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
106template< typename X >
107inline std::string fmt(const std::set< X >& val) {
108 return fmt_container( val, '{', '}' );
109}
110
111// formatting vectors using [ ... ] notation
112template< typename X >
113inline std::string fmt(const std::vector< X > &val) {
114 return fmt_container( val, '[', ']' );
115}
116
117// formatting vectors using [ ... ] notation
118template< typename X >
119inline std::string fmt(const std::deque< X > &val) {
120 return fmt_container( val, '[', ']' );
121}
122
124inline 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
134inline 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
151std::string normpath(const std::string& pathname);
152
154inline 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
162inline 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
169inline 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)
186template<typename FUN>
187inline 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
205inline std::string trim(const std::string& str)
206{
207 return trim(str, ::isspace);
208}
209#else
211inline 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
228inline 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
238inline 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
248inline 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
257inline 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
277inline 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
291std::string urlencode(const std::string& str);
292
294std::string urldecode(const std::string& str);
295
297std::string encodeBase64(const std::string& str);
298
300std::string decodeBase64(const std::string& str);
301
314class Split
315{
316 std::string sep;
317 std::string str;
318
319public:
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
405template<typename ITER>
406std::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{
437public:
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
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
476std::string c_escape(const std::string& str);
477
485std::string c_unescape(const std::string& str, size_t& lenParsed);
486
487
488}
489}
490
491// vim:set ts=4 sw=4:
492#endif
Definition string.h:322
bool operator!=(const const_iterator &ti) const
Definition string.h:385
const_iterator(const std::string &sep, const std::string &str)
Definition string.h:329
const std::string & operator*() const
Definition string.h:371
const_iterator(const std::string &sep, const std::string &str, bool)
Definition string.h:333
bool operator==(const const_iterator &ti) const
Definition string.h:379
std::string remainder() const
Definition string.h:363
const std::string * operator->() const
Definition string.h:375
const_iterator & operator++()
Definition string.h:335
Split a string where a given substring is found.
Definition string.h:315
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
const_iterator begin() const
Split the string and iterate the resulting tokens.
Definition string.h:401
const_iterator end() const
Definition string.h:402
const_iterator()
Definition string.h:447
const_iterator & operator++()
Definition string.cpp:318
bool operator==(const const_iterator &ti) const
Definition string.h:459
const std::pair< std::string, std::string > & operator*() const
Definition string.h:451
const std::pair< std::string, std::string > * operator->() const
Definition string.h:455
bool operator!=(const const_iterator &ti) const
Definition string.h:463
Parse a record of Yaml-style field: value couples.
Definition string.h:436
const_iterator end()
Definition string.h:470
const_iterator begin(std::istream &in)
Definition string.h:469
Definition operators.h:12
std::string fmt< char * >(char *const &val)
Definition string.h:84
std::string fmt_container(const C &c, char f, char l)
Definition string.h:87
std::string join(const ITER &begin, const ITER &end, const std::string &sep=", ")
Definition string.h:406
TPair< std::ostream, typenameX::Type >::First & operator<<(std::ostream &o, X list)
Definition string.h:56
std::string trim(const std::string &str, const FUN &classifier)
Return the substring of 'str' without all leading and trailing characters for which 'classifier' retu...
Definition string.h:187
std::string normpath(const std::string &pathname)
Normalise a pathname.
Definition string.cpp:133
std::string urlencode(const std::string &str)
Urlencode a string.
Definition string.cpp:160
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 dirname(const std::string &pathname)
Given a pathname, return the directory name without the file name.
Definition string.h:134
std::string toupper(const std::string &str)
Convert a string to uppercase.
Definition string.h:228
std::string urldecode(const std::string &str)
Decode an urlencoded string.
Definition string.cpp:178
bool endsWith(const std::string &str, const std::string &part)
Check if a string ends with the given substring.
Definition string.h:162
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
std::string appendpath(const std::string &path1, const std::string &path2)
Definition string.h:277
std::string decodeBase64(const std::string &str)
Decode a string encoded in Base64.
Definition string.cpp:241
std::string fmt< std::string >(const std::string &val)
Definition string.h:81
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 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 ucfirst(const std::string &str)
Return the same string, with the first character uppercased.
Definition string.h:248
std::string joinpath(const std::string &path1, const std::string &path2)
Join two paths, adding slashes when appropriate.
Definition string.h:257
std::string fmtf(const char *f,...)
Definition string.cpp:113
std::string tolower(const std::string &str)
Convert a string to lowercase.
Definition string.h:238
std::string basename(const std::string &pathname)
Given a pathname, return the file name without its path.
Definition string.h:124
std::string fmt(const char *f,...)
Definition string.cpp:123
Definition amorph.h:17
Definition amorph.h:30
A First
Definition sfinae.h:97