stringutil.h

Go to the documentation of this file.
00001 // ************************************************************ -*- C++ -*-
00006 /*
00007   AUTHOR(S): Stephan Broennimann (vb)
00008 
00009   RCS information
00010    $Name: OSB_060808 $
00011    $Revision: 1.14 $
00012 
00013   License
00014    OSB rating and billing library for communication networks
00015    Copyright (C) 2004, 2005, 2006  OSB systems
00016 
00017    This file may be distributed and/or modify under the terms of the
00018    GNU General Public License (GPL) as published by the Free Software
00019    Foundation which is provided in the file LICENSE.GPL included in the
00020    packaging of this file.
00021 
00022    The file is distributed in the hope that it will be useful, but WITHOUT
00023    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00024    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00025    for more details.
00026 
00027    Holders of a OSB Commercial License may use this file under the terms
00028    and conditions of this commercial license.
00029  */
00030 #ifndef _STRINGUTIL_H_
00031 #define _STRINGUTIL_H_
00032 
00033 // ************************************************************************
00034 // included header files
00035 // + standard includes
00036 #include <algorithm>
00037 #include <iterator>
00038 #include <sstream>
00039 #include <string>
00040 #include <limits>
00041 
00042 // + local headers
00043 
00044 // ************************************************************************
00045 // put version-info into object file
00046 namespace {
00047 }                                       // version info
00048 
00049 // ************************************************************************
00050 // namespace extensions
00051 namespace OSB_LIB {
00056     extern const std::string posixWs;
00057 
00064     void ltrim(
00065               std::string& s,
00066         const std::string& d = posixWs
00067     );
00068 
00075     void rtrim(
00076               std::string& s,
00077         const std::string& d = posixWs
00078     );
00079 
00086     void trim(
00087               std::string& s,
00088         const std::string& d = posixWs
00089     );
00090 
00098     bool endsWith(
00099         const std::string& str,
00100         const std::string& what
00101     );
00102 
00112     std::string lstrip(
00113         const std::string& from,
00114         const std::string& what
00115     );
00116 
00126     std::string rstrip(
00127         const std::string& from,
00128         const std::string& what
00129     );
00130 
00141     void escapeChars(
00142               std::string& str,
00143         const char         esc,
00144               size_t       maxLen
00145     );
00146 
00154     bool decDigitsOnly(
00155         const std::string& s
00156     );
00157 
00165     bool hexDigitsOnly(
00166         const std::string& s
00167     );
00168 
00180     template<typename Cont>
00181     void tokenize(
00182               Cont&        dest,
00183         const std::string& src,
00184         const std::string& del,
00185               bool         takeEmpty = false
00186     );
00187 
00199     template<typename Cont>
00200     void tokenize(
00201               Cont&        dest,
00202         const std::string& src
00203     );
00204 
00220     template<typename Cont>
00221     void stringTokenize(
00222               Cont&        dest,
00223         const std::string& src,
00224         const std::string& del,
00225               bool         takeEmpty = true
00226     );
00227 
00240     template<typename T>
00241     bool ston(
00242               T*           dest,
00243         const std::string& src,
00244               std::string* reminder = 0
00245     );
00246 
00256     template<typename T>
00257     std::string mkStr(const T& src);
00258 
00276     template<typename S = std::string>
00277     struct StrCmp : public std::binary_function<S, S, int> {
00279         explicit StrCmp(bool ignoreCase = false)
00280           : ignoreCase_(ignoreCase)
00281         {
00282             // empty
00283         }
00284 
00294         int operator()(
00295             const S& lhs,
00296             const S& rhs
00297         ) const;
00298     private:
00300         bool ignoreCase_;
00301     };                                  // struct StrCmp<S>
00302 
00310     template<typename S = std::string>
00311     struct LessStr : public std::binary_function<S, S, bool> {
00313         explicit LessStr(bool ignoreCase = false)
00314           : ignoreCase_(ignoreCase)
00315         {
00316             // empty
00317         }
00318 
00320         bool operator()(
00321             const S& lhs,
00322             const S& rhs
00323         ) const
00324         {
00325             return 0 > StrCmp<S>(ignoreCase_)(lhs, rhs);
00326         }
00327     private:
00329         bool ignoreCase_;
00330     };                                  // struct LessStr<S>
00331 
00339     template<typename S = std::string>
00340     struct GreaterStr : public std::binary_function<S, S, bool> {
00342         explicit GreaterStr(bool ignoreCase = false)
00343           : ignoreCase_(ignoreCase)
00344         {
00345             // empty
00346         }
00347 
00349         inline bool operator()(
00350             const S& lhs,
00351             const S& rhs
00352         ) const
00353         {
00354             return 0 < StrCmp<S>(ignoreCase_)(lhs, rhs);
00355         }
00356     private:
00358         bool ignoreCase_;
00359     };                                  // struct GreaterStr<S>
00360 
00372     template<typename T, typename S = std::string>
00373     struct LessName : public std::binary_function<T, T, bool> {
00375         explicit LessName(bool ignoreCase = false)
00376           : ignoreCase_(ignoreCase)
00377         {
00378             // empty
00379         }
00380 
00382         inline bool operator()(
00383             const T& lhs,
00384             const T& rhs
00385         ) const
00386         {
00387             return LessStr<S>(ignoreCase_)(lhs.name(), rhs.name());
00388         }
00389     private:
00391         bool ignoreCase_;
00392     };                                  // struct LessName<T, S>
00393 
00406     template<typename T, typename S>
00407     struct LessName<T*, S> : public std::binary_function<T, T, bool> {
00409         LessName(bool ignoreCase = false)
00410           : ignoreCase_(ignoreCase)
00411         {
00412         }
00413 
00415         inline bool operator()(
00416             const T* lhs,
00417             const T* rhs
00418         ) const
00419         {
00420             return LessStr<S>(ignoreCase_)(lhs->name(), rhs->name());
00421         }
00422     private:
00424         bool ignoreCase_;
00425     };                                  // struct LessName<T*, S>
00426 
00459     template<typename T, typename S = std::string>
00460     struct GreaterName : public std::binary_function<T, T, bool> {
00462         GreaterName(bool ignoreCase = false)
00463           : ignoreCase_(ignoreCase)
00464         {
00465         }
00466 
00468         inline bool operator()(
00469             const T& lhs,
00470             const T& rhs
00471         ) const
00472         {
00473             return GreaterStr<S>(ignoreCase_)(lhs.name(), rhs.name());
00474         }
00475     private:
00477         bool ignoreCase_;
00478     };                                  // struct GreaterName<T, S>
00479 
00490     template<typename T, typename S>
00491     struct GreaterName<T*, S> : public std::binary_function<T, T, bool> {
00493         GreaterName(bool ignoreCase = false)
00494           : ignoreCase_(ignoreCase)
00495         {
00496         }
00497 
00499         inline bool operator()(
00500             const T* lhs,
00501             const T* rhs
00502         ) const
00503         {
00504             return GreaterStr<S>(ignoreCase_)(lhs->name(), rhs->name());
00505         }
00506     private:
00508         bool ignoreCase_;
00509     };                                  // struct GreaterName<T*, S>
00510 }                                       // namespace OSB_LIB
00511 
00512 // ************************************************************************
00513 // inline definitions
00514 namespace OSB_LIB {
00515     template<typename Cont>
00516     void tokenize(
00517               Cont&        dest,
00518         const std::string& src,
00519         const std::string& del,
00520               bool         takeEmpty
00521     )
00522     {
00523         using std::string;
00524         string::size_type len      = src.length();
00525         string::size_type startPos = 0;
00526         string::size_type endPos   = string::npos;
00527 
00528         dest.clear();
00529         while (startPos < len) {
00530             if (!takeEmpty) {
00531                 // Skip leading delimiters
00532                 startPos = src.find_first_not_of(del, startPos);
00533                 // No non-delimiter found: return
00534                 if (string::npos == startPos) return;
00535             }
00536 
00537             // Find end of token
00538             endPos = src.find_first_of(del, startPos);
00539             // Delimiter found: isolate the token.
00540             if (string::npos != endPos) {
00541                 dest.push_back(src.substr(startPos, endPos-startPos));
00542                 // Advance in src: examine next character
00543                 startPos = endPos+1;
00544             }
00545             // No more delimiters: get the reminder and return.
00546             else {
00547                 dest.push_back(src.substr(startPos));
00548                 return;
00549             }
00550         }
00551         // We only come here if the last character is a delimiter
00552         if (takeEmpty && string::npos != endPos) {
00553             dest.push_back(src.substr(endPos+1));
00554         }
00555     }
00556 
00557     template<typename Cont>
00558     inline void tokenize(
00559               Cont&        dest,
00560         const std::string& src
00561     )
00562     {
00563         return tokenize(dest, src, posixWs);
00564     }
00565 
00566     template<typename Cont>
00567     void stringTokenize(
00568               Cont&        dest,
00569         const std::string& src,
00570         const std::string& del,
00571               bool         takeEmpty
00572     )
00573     {
00574         using std::string;
00575 
00576         dest.clear();
00577 
00578         // special case: if the delimiter string is empty we
00579         // put the whole `src' to the result and return
00580         if (del.empty()) {
00581             dest.push_back(src);
00582             if (!takeEmpty && dest.back().empty()) dest.pop_back();
00583             return;
00584         }
00585 
00586         string::size_type srclen   = src.length();
00587         string::size_type dellen   = del.length();
00588         string::size_type startPos = 0;
00589 
00590         while (startPos < srclen) {
00591             // find end of token
00592             string::size_type endPos = src.find(del, startPos);
00593             // no more delimiters: exit the while loop
00594             if (string::npos == endPos) break;
00595 
00596             // delimiter found: isolate the token and advance
00597             dest.push_back(src.substr(startPos, endPos-startPos));
00598             if (!takeEmpty && dest.back().empty()) dest.pop_back();
00599             // advance in src: examine next characters
00600             startPos = endPos + dellen;
00601         }
00602         dest.push_back(src.substr(startPos));
00603         if (!takeEmpty && dest.back().empty()) dest.pop_back();
00604     }
00605 
00606     template<typename T>
00607     bool ston(
00608               T*           dest,
00609         const std::string& src,
00610               std::string* reminder
00611     )
00612     {
00613         typedef std::istream_iterator<char> Iter;
00614 
00615         bool rc = false;
00616         T t = T();
00617 
00618         std::numeric_limits<T> limits;
00619         if (limits.is_integer) {
00620             char* err = 0;
00621 
00622             if (limits.is_signed) t = strtol(src.c_str(), &err, 0);
00623             else                  t = strtoul(src.c_str(), &err, 0);
00624 
00625             if (0 == err || 0 == *err) {
00626                 rc = true;
00627             }
00628             else if (0 != reminder) {
00629                 *reminder = std::string(err);
00630             }
00631         }
00632         else {
00633             std::istringstream is(src);
00634             is >> t;
00635             rc = is && is.eof();
00636 
00637             if (!rc && 0 != reminder) {
00638                 is.clear();
00639                 is >> std::noskipws;
00640                 std::copy(Iter(is), Iter(), std::back_inserter(*reminder));
00641             }
00642         }
00643 
00644         if (rc) *dest = t;
00645         return rc;
00646     }
00647 
00648     template<typename T>
00649     std::string mkStr(const T& src)
00650     {
00651         std::ostringstream rc;
00652         rc << src;
00653         return rc.str();
00654     }
00655 
00656     // ********************************************************************
00657     // struct StrCmp<S>
00658     template<typename S> int StrCmp<S>::operator()(
00659         const S& lhs,
00660         const S& rhs
00661     ) const
00662     {
00663         typedef typename S::const_iterator Iter;
00664 
00665         if (!ignoreCase_) return lhs.compare(rhs);
00666 
00667         Iter le = lhs.end();
00668         Iter re = rhs.end();
00669         Iter li = lhs.begin();
00670         Iter ri = rhs.begin();
00671 
00672         for (;li != le && ri != re; ++li, ++ri) {
00673             char l = toupper(*li);
00674             char r = toupper(*ri);
00675             if (l != r) {
00676                 return (l < r) ? -1 : 1;
00677             }
00678         }
00679 
00680         if (li == le && ri == re) {
00681             // we're at the end of both strings: lhs == rhs
00682             return 0;
00683         }
00684         else if (li == le) {
00685             // we're at the end of lhs, i.e., lhs < rhs
00686             return -1;
00687         }
00688         // we're at the end of rhs, i.e., lhs > rhs
00689         return 1;
00690     }
00691 }                                       // namespace OSB_LIB
00692 #endif                                  // #ifndef _STRINGUTIL_H_

Generated on Sat Sep 2 14:06:34 2006 for OSB Library by  doxygen 1.4.7