OKlibrary  0.2.1.6
StringHandling.hpp
Go to the documentation of this file.
00001 // Oliver Kullmann, 29.5.2002 (Swansea)
00002 /* Copyright 2002 - 2007 Oliver Kullmann
00003 This file is part of the OKlibrary. OKlibrary is free software; you can redistribute
00004 it and/or modify it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation and included in this library; either version 3 of the
00006 License, or any later version. */
00007 
00014 #ifndef STRINGHANDLINGWAECHTER
00015 
00016 #define STRINGHANDLINGWAECHTER
00017 
00018 #include <string>
00019 #include <sstream>
00020 #include <functional>
00021 #include <cctype>
00022 #include <algorithm>
00023 #include <cstdlib>
00024 #include <vector>
00025 #include <limits>
00026 #include <cassert>
00027 
00028 #include <OKlib/General/ErrorHandling.hpp>
00029 
00030 namespace StringHandling {
00031 
00032   struct Error : ErrorHandling::Error {
00033     Error(const std::string& what) : ErrorHandling::Error(what) {}
00034   };
00035 
00036 }
00037 
00038 // -----------------------------
00039 // C-string
00040 // -----------------------------
00041 
00042 namespace StringHandling {
00043 
00044   inline char *copy_new(const std::string s) {
00045     // returned string must be deleted with "delete []"
00046     const std::string::size_type l = s.size();
00047     char* p = new char[l+1];
00048     s.copy(p, l);
00049     p[l] = 0;
00050     return p;
00051   }
00052 
00053   class Vector_c_str {
00054     // members must have been generated with new []
00055   public :
00056     typedef std::vector<char *> vec_char;
00057     vec_char v;
00058     Vector_c_str() {}
00059     ~ Vector_c_str() {
00060       for (vec_char::iterator i = v.begin(); i != v.end(); ++i)
00061   delete[] *i;
00062     }
00063     void push_back(const std::string& s) {
00064       v.push_back(copy_new(s));
00065     }
00066     void clear() {
00067       for (vec_char::iterator i = v.begin(); i != v.end(); ++i)
00068   delete[] *i;
00069       v.clear();
00070     }
00071       
00072   private :
00073     Vector_c_str(const Vector_c_str&);
00074     Vector_c_str& operator = (const Vector_c_str&);
00075   };
00076 
00077 }
00078 // -----------------------------
00079 // Conversions
00080 // -----------------------------
00081 
00082 namespace StringHandling {
00083 
00084   namespace Error_StringHandling {
00085     struct conversion_to_string : Error {
00086       conversion_to_string(const std::string& what) : Error(what) {}
00087     };
00088     struct conversion_from_string : Error {
00089       conversion_from_string(const std::string& what) : Error(what) {}
00090     };
00091   }
00092 
00093   template<typename T> inline std::string toString(const T& x) {
00094     // throw(Error_StringHandling::conversion_to_string(), std::ios_base::failure)
00095     std::ostringstream s;
00096     s << x;
00097     if (! s)
00098       throw Error_StringHandling::conversion_to_string(std::string("StringHandling::toString : Can not convert value of type ") + typeid(T).name() + " to string");
00099     return s.str();
00100   }
00101   inline std::string toString(unsigned char x) {
00102     // throw(Error_StringHandling::conversion_to_string(), std::ios_base::failure)
00103     std::ostringstream s;
00104     s << int(x);
00105     if (! s)
00106       throw Error_StringHandling::conversion_to_string(std::string("StringHandling::toString : Can not convert value of type ") + typeid(char).name() + " to string");
00107     return s.str();
00108   }
00109   inline std::string toString(signed char x) {
00110     // throw(Error_StringHandling::conversion_to_string(), std::ios_base::failure)
00111     std::ostringstream s;
00112     s << int(x);
00113     if (! s)
00114       throw Error_StringHandling::conversion_to_string(std::string("StringHandling::toString : Can not convert value of type ") + typeid(char).name() + " to string");
00115     return s.str();
00116   }
00117   template<typename T> inline std::string toString_nc(const T& x) {
00118     // "nc" : not checked
00119     // throw(std::ios_base::failure)
00120     std::ostringstream s;
00121     s << x;
00122     return s.str();
00123   }
00124   inline std::string toString_nc(unsigned char x) {
00125     // "nc" : not checked
00126     // throw(std::ios_base::failure)
00127     std::ostringstream s;
00128     s << int(x);
00129     return s.str();
00130   }
00131   inline std::string toString_nc(signed char x) {
00132     // "nc" : not checked
00133     // throw(std::ios_base::failure)
00134     std::ostringstream s;
00135     s << int(x);
00136     return s.str();
00137   }
00138 
00139   
00140   
00141 
00142   template<typename T> inline T fromString(const std::string& st) {
00143     // throw(Error_StringHandling::conversion_from_string(), std::ios_base::failure)
00144     std::istringstream s(st);
00145     T x;
00146     s >> x;
00147     if (! s)
00148       throw Error_StringHandling::conversion_from_string(std::string("StringHandling::fromString : Can not convert string \"") + st + "\" into value of type " + typeid(T).name());
00149     return x;
00150   }
00151   template<typename T> inline T fromString_nc(const std::string& st) {
00152     // throw(std::ios_base::failure)
00153     std::istringstream s(st);
00154     T x;
00155     s >> x;
00156     return x;
00157   }
00158 
00159 
00160 }
00161 
00162 // -----------------------------
00163 // Classifying Characters
00164 // -----------------------------
00165 
00166 struct isSpace : std::unary_function<char, bool> {
00167   bool operator() (const char c) const {
00168     return std::isspace(c);
00169     // uses the current global C locale
00170   }
00171 };
00172 
00173 
00174 // -----------------------------
00175 // Erasing Characters
00176 // -----------------------------
00177 
00178 namespace StringHandling {
00179 
00180   inline std::string deleteCharacter(std::string s, const char c) {
00181     // throw()
00182     s.erase(remove(s.begin(), s.end(), c), s.end());
00183     return s;
00184   }
00185 
00186   inline void deleteCharacter_var(std::string& s, const char c) {
00187     // throw()
00188     s.erase(remove(s.begin(), s.end(), c), s.end());
00189   }
00190 
00191   inline std::string deleteSpaces(std::string s) {
00192     // throw()
00193     s.erase(remove_if(s.begin(), s.end(), isSpace()), s.end());
00194     return s;
00195   }
00196 
00197   inline void deleteSpaces_var(std::string& s) {
00198     // throw()
00199     s.erase(remove_if(s.begin(), s.end(), isSpace()), s.end());
00200   }
00201 
00202   inline std::string deleteHead(const std::string& s, const int n) {
00203     // throw()
00204     assert(n != std::numeric_limits<int>::min()); // TODO Write a better abs-function, which for input int returns unsigned int, so that this asserts becomes superfluous.
00205     if (n == 0)
00206       return s;
00207     else if ((unsigned int) std::abs(n) >= s.size())
00208       return "";
00209     else if (n > 0)
00210       return s.substr(n);
00211     else
00212       return s.substr(0, s.size() + n);
00213   }
00214 
00215   inline void deleteHead_var(std::string& s, const int n) {
00216     // throw()
00217     assert(n != std::numeric_limits<int>::min()); // TODO see above for abs-function
00218     if ((unsigned int) std::abs(n) >= s.size()) {
00219       s.clear();
00220     }
00221     else if (n > 0)
00222       s.erase(0, n);
00223     else
00224       s.erase(s.size() + n);
00225   }
00226 
00227 // -----------------------------
00228 // Replacing substrings
00229 // -----------------------------
00230 
00231   // The following three functions replace the first occurrence of the sub-string to_be_replaced of the string original with the string substitute.
00232   // The differ how they react in case the sub-string is in fact not a sub-string.
00233   // In any case, the string original is not changed if the sub-string is in fact not a sub-string.
00234   // All throws std::length_error if the resulting string is too big.
00235 
00236   inline void replace_substring_throw(std::string& original, const std::string& to_be_replaced, const std::string& substitute) {
00237     // throws std::out_of_range in case to_be_replaced is not a substring of original
00238     // throws std::length_error if resulting string is too big
00239     // to catch these exceptions, include <stdexcept>;
00240     // both exception classes are derived from std::logic_error,
00241     // which again is derived from std::exception (include <exception> for the latter)
00242     original.replace(original.find(to_be_replaced), to_be_replaced.size(), substitute);
00243   }
00244 
00245   inline bool replace_substring_check(std::string& original, const std::string& to_be_replaced, const std::string& substitute) {
00246     // throws std::length_error if resulting string is too big
00247     const std::string::size_type pos = original.find(to_be_replaced);
00248     if (pos == std::string::npos)
00249       return false;
00250     else {
00251       original.replace(pos, to_be_replaced.size(), substitute);
00252       return true;
00253     }
00254   }
00255 
00256   inline void replace_substring_if_possible(std::string& original, const std::string& to_be_replaced, const std::string& substitute) {
00257     // throws std::length_error if resulting string is too big
00258     const std::string::size_type pos = original.find(to_be_replaced);
00259     if (pos == std::string::npos)
00260       return;
00261     else {
00262       original.replace(pos, to_be_replaced.size(), substitute);
00263       return;
00264     }
00265   }
00266 
00267   // The following function replaces all occurrences of the string
00268   // "to_be_replaced" by "substitute" (simultaneously).
00269 
00270   inline void replace_all_substrings(std::string& original, const std::string& to_be_replaced, const std::string& substitute) {
00271     // throws std::length_error if resulting string is too big
00272     const std::string::size_type size_substitute = substitute.size();
00273     const std::string::size_type size_replaced = to_be_replaced.size();
00274     for (std::string::size_type pos = 0; (pos = original.find(to_be_replaced, pos)) != std::string::npos; pos += size_substitute)
00275       original.replace(pos, size_replaced, substitute);
00276   }
00277   
00278 }
00279 
00280 
00281 #endif