string.h
Go to the documentation of this file.
// -*- C++ -*-
#ifndef WIBBLE_STRING_H
#define WIBBLE_STRING_H
/*
* Various string functions
*
* Copyright (C) 2007,2008 Enrico Zini <enrico@debian.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <wibble/operators.h>
#include <wibble/sfinae.h>
#include <cstdarg>
#include <cstdio>
#include <string>
#include <set>
#include <vector>
#include <deque>
#include <sstream>
#include <cctype>
#ifdef _WIN32
#include <cstring>
#include <cstdlib>
#endif
namespace wibble {
namespace str {
using namespace wibble::operators;
#ifdef _WIN32
static int vasprintf (char **, const char *, va_list);
#endif
std::string fmtf( const char* f, ... );
template< typename T > inline std::string fmt(const T& val);
// Formatting lists -- actually, we need to move list handling into wibble,
// really.
template< typename X >
inline typename TPair< std::ostream, typename X::Type >::First &operator<<(
std::ostream &o, X list )
{
if ( list.empty() )
return o << "[]";
o << "[ ";
while( !list.empty() ) {
o << fmt( list.head() );
if ( !list.tail().empty() )
o << ", ";
list = list.tail();
}
return o << " ]";
}
template< typename T >
inline std::string fmt(const T& val)
{
std::stringstream str;
str << val;
return str.str();
}
template<> inline std::string fmt<std::string>(const std::string& val) {
return val;
}
template<> inline std::string fmt<char*>(char * const & val) { return val; }
template< typename C >
inline std::string fmt_container( const C &c, char f, char l )
{
std::string s;
s += f;
if ( c.empty() )
return s + l;
s += ' ';
for ( typename C::const_iterator i = c.begin(); i != c.end(); ++i ) {
s += fmt( *i );
if ( i != c.end() && i + 1 != c.end() )
s += ", ";
}
s += ' ';
s += l;
return s;
}
// formatting sets using { ... } notation
template< typename X >
inline std::string fmt(const std::set< X >& val) {
return fmt_container( val, '{', '}' );
}
// formatting vectors using [ ... ] notation
template< typename X >
inline std::string fmt(const std::vector< X > &val) {
return fmt_container( val, '[', ']' );
}
// formatting vectors using [ ... ] notation
template< typename X >
inline std::string fmt(const std::deque< X > &val) {
return fmt_container( val, '[', ']' );
}
inline std::string basename(const std::string& pathname)
{
size_t pos = pathname.rfind("/");
if (pos == std::string::npos)
return pathname;
else
return pathname.substr(pos+1);
}
inline std::string dirname(const std::string& pathname)
{
size_t pos = pathname.rfind("/");
if (pos == std::string::npos)
return std::string();
else if (pos == 0)
// Handle the case of '/foo'
return std::string("/");
else
return pathname.substr(0, pos);
}
std::string normpath(const std::string& pathname);
inline bool startsWith(const std::string& str, const std::string& part)
{
if (str.size() < part.size())
return false;
return str.substr(0, part.size()) == part;
}
inline bool endsWith(const std::string& str, const std::string& part)
{
if (str.size() < part.size())
return false;
return str.substr(str.size() - part.size()) == part;
}
inline std::string replace(const std::string& str, char from, char to)
{
std::string res;
res.reserve(str.size());
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
if (*i == from)
res.append(1, to);
else
res.append(1, *i);
return res;
}
#if !__xlC__ && (! __GNUC__ || __GNUC__ >= 4)
template<typename FUN>
inline std::string trim(const std::string& str, const FUN& classifier)
{
if (str.empty())
return str;
size_t beg = 0;
size_t end = str.size() - 1;
while (beg < end && classifier(str[beg]))
++beg;
while (end >= beg && classifier(str[end]))
--end;
return str.substr(beg, end-beg+1);
}
inline std::string trim(const std::string& str)
{
return trim(str, ::isspace);
}
#else
inline std::string trim(const std::string& str)
{
if (str.empty())
return str;
size_t beg = 0;
size_t end = str.size() - 1;
while (beg < end && ::isspace(str[beg]))
++beg;
while (end >= beg && ::isspace(str[end]))
--end;
return str.substr(beg, end-beg+1);
}
#endif
inline std::string toupper(const std::string& str)
{
std::string res;
res.reserve(str.size());
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
res += ::toupper(*i);
return res;
}
inline std::string tolower(const std::string& str)
{
std::string res;
res.reserve(str.size());
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
res += ::tolower(*i);
return res;
}
inline std::string ucfirst(const std::string& str)
{
if (str.empty()) return str;
std::string res;
res += ::toupper(str[0]);
return res + tolower(str.substr(1));
}
inline std::string joinpath(const std::string& path1, const std::string& path2)
{
if (path1.empty())
return path2;
if (path2.empty())
return path1;
if (path1[path1.size() - 1] == '/')
if (path2[0] == '/')
return path1 + path2.substr(1);
else
return path1 + path2;
else
if (path2[0] == '/')
return path1 + path2;
else
return path1 + '/' + path2;
}
// append path2 to path1 if path2 is not absolute, otherwise return path2
inline std::string appendpath( const std::string &path1, const std::string &path2 ) {
#ifdef POSIX
if ( path2.size() >= 1 && path2[ 0 ] == '/' )
return path2;
#endif
#ifdef WIN32
if ( ( path2.size() >= 3 && path2[ 1 ] == ':' && path2[ 2 ] == '\\' )
|| ( path2.size() >= 2 && path2[ 0 ] == '\\' && path2[ 1 ] == '\\' ) )
return path2;
#endif
return joinpath( path1, path2 );
}
std::string urlencode(const std::string& str);
std::string urldecode(const std::string& str);
std::string encodeBase64(const std::string& str);
std::string decodeBase64(const std::string& str);
class Split
{
std::string sep;
std::string str;
public:
// TODO: add iterator_traits
class const_iterator
{
const std::string& sep;
const std::string& str;
std::string cur;
size_t pos;
public:
const_iterator(const std::string& sep, const std::string& str) : sep(sep), str(str), pos(0)
{
++*this;
}
const_iterator(const std::string& sep, const std::string& str, bool) : sep(sep), str(str), pos(std::string::npos) {}
const_iterator& operator++()
{
if (pos == str.size())
pos = std::string::npos;
else
{
size_t end;
if (sep.empty())
if (pos + 1 == str.size())
end = std::string::npos;
else
end = pos + 1;
else
end = str.find(sep, pos);
if (end == std::string::npos)
{
cur = str.substr(pos);
pos = str.size();
}
else
{
cur = str.substr(pos, end-pos);
pos = end + sep.size();
}
}
return *this;
}
std::string remainder() const
{
if (pos == std::string::npos)
return std::string();
else
return str.substr(pos);
}
const std::string& operator*() const
{
return cur;
}
const std::string* operator->() const
{
return &cur;
}
bool operator==(const const_iterator& ti) const
{
// Comparing iterators on different strings is not supported for
// performance reasons
return pos == ti.pos;
}
bool operator!=(const const_iterator& ti) const
{
// Comparing iterators on different strings is not supported for
// performance reasons
return pos != ti.pos;
}
};
Split(const std::string& sep, const std::string& str) : sep(sep), str(str) {}
const_iterator begin() const { return const_iterator(sep, str); }
const_iterator end() const { return const_iterator(sep, str, false); }
};
template<typename ITER>
std::string join(const ITER& begin, const ITER& end, const std::string& sep = ", ")
{
std::stringstream res;
bool first = true;
for (ITER i = begin; i != end; ++i)
{
if (first)
first = false;
else
res << sep;
res << *i;
}
return res.str();
}
class YamlStream
{
public:
// TODO: add iterator_traits
class const_iterator
{
std::istream* in;
std::pair<std::string, std::string> value;
std::string line;
public:
const_iterator(std::istream& in);
const_iterator() : in(0) {}
const_iterator& operator++();
const std::pair<std::string, std::string>& operator*() const
{
return value;
}
const std::pair<std::string, std::string>* operator->() const
{
return &value;
}
bool operator==(const const_iterator& ti) const
{
return in == ti.in;
}
bool operator!=(const const_iterator& ti) const
{
return in != ti.in;
}
};
const_iterator begin(std::istream& in) { return const_iterator(in); }
const_iterator end() { return const_iterator(); }
};
std::string c_escape(const std::string& str);
std::string c_unescape(const std::string& str, size_t& lenParsed);
}
}
// vim:set ts=4 sw=4:
#endif
wibble::str::joinpath
std::string joinpath(const std::string &path1, const std::string &path2)
Join two paths, adding slashes when appropriate.
Definition: string.h:257
wibble::str::YamlStream::const_iterator::operator->
const std::pair< std::string, std::string > * operator->() const
Definition: string.h:455
wibble::str::c_escape
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
wibble::str::toupper
std::string toupper(const std::string &str)
Convert a string to uppercase.
Definition: string.h:228
wibble::str::YamlStream::const_iterator::operator*
const std::pair< std::string, std::string > & operator*() const
Definition: string.h:451
wibble::str::Split::const_iterator::operator==
bool operator==(const const_iterator &ti) const
Definition: string.h:379
std
wibble::str::appendpath
std::string appendpath(const std::string &path1, const std::string &path2)
Definition: string.h:277
wibble::str::YamlStream::end
const_iterator end()
Definition: string.h:470
wibble::str::Split
Split a string where a given substring is found.
Definition: string.h:314
wibble::str::Split::begin
const_iterator begin() const
Split the string and iterate the resulting tokens.
Definition: string.h:401
wibble::TPair::First
A First
Definition: sfinae.h:97
wibble::list::begin
ListIterator< List > begin(List l)
Definition: list.h:420
wibble::str::YamlStream::const_iterator::operator!=
bool operator!=(const const_iterator &ti) const
Definition: string.h:463
wibble::str::YamlStream::begin
const_iterator begin(std::istream &in)
Definition: string.h:469
wibble::operators
Definition: operators.h:12
wibble::str::Split::const_iterator::operator!=
bool operator!=(const const_iterator &ti) const
Definition: string.h:385
wibble::str::fmt< char * >
std::string fmt< char * >(char *const &val)
Definition: string.h:84
wibble::str::urldecode
std::string urldecode(const std::string &str)
Decode an urlencoded string.
Definition: string.cpp:178
wibble::str::fmt
std::string fmt(const char *f,...)
Definition: string.cpp:123
wibble::str::basename
std::string basename(const std::string &pathname)
Given a pathname, return the file name without its path.
Definition: string.h:124
wibble::str::encodeBase64
std::string encodeBase64(const std::string &str)
Encode a string in Base64.
Definition: string.cpp:208
wibble::str::replace
std::string replace(const std::string &str, char from, char to)
Definition: string.h:169
wibble::str::operator<<
TPair< std::ostream, typename X::Type >::First & operator<<(std::ostream &o, X list)
Definition: string.h:56
wibble::str::YamlStream::const_iterator::const_iterator
const_iterator()
Definition: string.h:447
sfinae.h
operators.h
wibble::str::YamlStream::const_iterator
Definition: string.h:439
wibble::str::Split::const_iterator::operator++
const_iterator & operator++()
Definition: string.h:335
wibble::str::Split::const_iterator::remainder
std::string remainder() const
Definition: string.h:363
wibble::str::YamlStream::const_iterator::operator==
bool operator==(const const_iterator &ti) const
Definition: string.h:459
wibble::str::Split::const_iterator::const_iterator
const_iterator(const std::string &sep, const std::string &str)
Definition: string.h:329
wibble::str::YamlStream
Parse a record of Yaml-style field: value couples.
Definition: string.h:435
wibble::str::Split::const_iterator::operator*
const std::string & operator*() const
Definition: string.h:371
wibble::str::normpath
std::string normpath(const std::string &pathname)
Normalise a pathname.
Definition: string.cpp:133
wibble::str::Split::const_iterator
Definition: string.h:321
wibble::str::ucfirst
std::string ucfirst(const std::string &str)
Return the same string, with the first character uppercased.
Definition: string.h:248
wibble
Definition: amorph.h:17
wibble::str::endsWith
bool endsWith(const std::string &str, const std::string &part)
Check if a string ends with the given substring.
Definition: string.h:162
wibble::str::Split::Split
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
wibble::str::startsWith
bool startsWith(const std::string &str, const std::string &part)
Check if a string starts with the given substring.
Definition: string.h:154
wibble::str::dirname
std::string dirname(const std::string &pathname)
Given a pathname, return the directory name without the file name.
Definition: string.h:134
wibble::str::trim
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
wibble::str::tolower
std::string tolower(const std::string &str)
Convert a string to lowercase.
Definition: string.h:238
wibble::str::Split::end
const_iterator end() const
Definition: string.h:402
wibble::str::decodeBase64
std::string decodeBase64(const std::string &str)
Decode a string encoded in Base64.
Definition: string.cpp:241
wibble::str::urlencode
std::string urlencode(const std::string &str)
Urlencode a string.
Definition: string.cpp:160
wibble::str::fmt_container
std::string fmt_container(const C &c, char f, char l)
Definition: string.h:87
wibble::str::Split::const_iterator::const_iterator
const_iterator(const std::string &sep, const std::string &str, bool)
Definition: string.h:333
wibble::str::c_unescape
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
wibble::list::end
ListIterator< List > end(List)
Definition: list.h:425
wibble::str::Split::const_iterator::operator->
const std::string * operator->() const
Definition: string.h:375
wibble::str::fmtf
std::string fmtf(const char *f,...)
Definition: string.cpp:113
wibble::str::join
std::string join(const ITER &begin, const ITER &end, const std::string &sep=", ")
Definition: string.h:406