1 /*-----------------------------------------------------------------------------
  2 Name:      StringTrim.h
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Helper to emulate the java String.trim() method
  6 Author:    <Michele Laghi> laghi@swissinfo.org
  7 -----------------------------------------------------------------------------*/
  8 
  9 #ifndef _UTIL_STRINGTRIM_H
 10 #define _UTIL_STRINGTRIM_H
 11 
 12 #include <util/XmlBCfg.h>
 13 #include <ctype.h>  // ::tolower
 14 #include <string>
 15 #include <util/lexical_cast.h>
 16 
 17 #define  EMPTY_STRING std::string("")
 18 
 19 
 20 
 21 namespace org { namespace xmlBlaster {
 22 namespace util {
 23    
 24    /**
 25     * This template class is used to trim a std::string the same way the String.trim
 26     * java method does. It can be instantiated with which character type you
 27     * want and will therefore work even with xerces XMLCh* std::strings. </p>
 28     * This class is part of the package because the XMLString::trim(...) 
 29     * method in the xerces package does not fullfill our requirements.
 30     */
 31    class Dll_Export StringTrim
 32    {
 33    public:
 34       
 35       /** 
 36        * Default constructor. Does nothing
 37        */
 38       StringTrim()
 39       {
 40       }
 41 
 42       /**
 43        * This method converts a string to lowercase. Note that the input string is
 44        * modified and a reference to it is returned.
 45        */
 46       static std::string& toLowerCase(std::string& ref)
 47       {
 48          std::string::iterator iter = ref.begin();
 49          while (iter != ref.end()) {
 50             *iter = ::tolower(*iter);
 51             iter++;
 52          }
 53          return ref;
 54       }
 55 
 56       /**
 57        * Replace all occurrences of "from" with to "to".
 58        */
 59       static std::string replaceAll(const std::string &str, const std::string &from, const std::string &to) {
 60          if (str.empty() || from.empty() || to.empty())
 61             return str;
 62          if (str.find(from) == std::string::npos)
 63             return str;
 64 
 65          std::string buf;
 66          std::string tail = str;
 67          while (true) {
 68             std::string::size_type index = tail.find(from);
 69             if (index != std::string::npos) {
 70                if (index > 0)
 71                   buf += tail.substr(0, index);
 72                buf += to;
 73                tail = tail.substr(index + from.size());
 74             }
 75             else
 76                break;
 77          }
 78          buf += tail;
 79          return buf;
 80       }
 81 
 82       /**
 83        * Checks string to be interpreted as true. 
 84        * If you don't need trimming please use <i>lexical_cast<bool>(str)</i> instead of this method.
 85        * @param str The checked std::string (is not modified)
 86        * @return true if trimmed std::string is "TRUE" or "true" or "1" else false
 87        */
 88       static bool isTrue(const std::string& str) {
 89          std::string tmp = trim(str.c_str());
 90          return lexical_cast<bool>(tmp);
 91       }
 92 
 93       /**
 94        * Evaluate trimmed boolean string. 
 95        * @param str The checked std::string (is not modified)
 96        * @param def Default value to use if str not one of described below
 97        * @return true if trimmed std::string is "TRUE" or "true" or "1" else false
 98        *         false if trimmed "0", "false", "FALSE"
 99        */
100       static bool isTrue(const std::string& str, bool def) {
101          std::string value = trim(str);
102          if (value.length() == 0) return def;
103          if (isTrue(value) == true) return true;
104          if ((value=="0")||(value=="false")||(value=="FALSE")) return false;
105          return def;
106       }
107 
108       /**
109        * Use this method instead of isTrue(std::string&) if your input std::string may
110        * be manipulated (it performs a bit better then the other method). 
111        * NOTE: It returns true if the str is empty, this is nice for SAX parse
112        * where <persistent/> also triggers an endElement() with empty character_ and means 'true'.
113        * @param str The checked std::string (is trimmed!!)
114        * @return true if trimmed std::string is "TRUE" or "true" or "1" or "" else false
115        */
116       static bool isTrueTrim(std::string& str) {
117          trim(str);
118          if (str.length() == 0) return true;
119          return lexical_cast<bool>(str);
120       }
121 
122       /**
123        * returns the length of the character std::string str. (by detecting the 
124        * first occurence of zero.
125        */
126        /*
127       static int std::stringLength(const char *str)
128       {
129          int count = 0;
130          while (str[count] != (char)0) count++;
131          return count;
132       }
133         */
134 
135       /**
136        * Trims the start of the std::string (whitespaces, newlines etc.). 
137        */
138       static std::string trimStart(const char *str)
139       {
140          if (str == static_cast<const char *>(0)) return EMPTY_STRING;
141 
142          int start = 0;
143          while (str[start] != 0)
144             if (isspace(str[start++]))
145                continue;
146             else
147                return std::string(str + (start-1));
148 
149          return EMPTY_STRING;
150       }
151       
152 
153       /**
154        * @param str The given std::string will be trimmed (in - out parameter)
155        * @param Returns the trimmed given parameter (the str instance)
156        * @see #trimStart(const char *)
157        */
158       static std::string& trimStart(std::string &str)
159       {
160          if (str.capacity() < 1) return str;
161 
162          if (str.length() < 1)
163             return str;
164          if (!isspace(str[0]))
165             return str;
166 
167          for (std::string::size_type ii=1; ii<str.length(); ii++) {
168             if (!isspace(str[ii])) {
169                str = str.substr(ii);
170                return str;
171             }
172          }
173 
174          return str;
175       }
176 
177       /**
178        * Trims all spaces from the end of the std::string (whitespaces, newlines etc). 
179        */
180       static std::string trimEnd(const char *str)
181       {
182          if (str == static_cast<const char *>(0) || *str == 0) return EMPTY_STRING;
183          std::string strip(str);
184          trimEnd(strip);
185          return strip;
186       }      
187 
188       /**
189        * @param str The given std::string will be trimmed (in - out parameter)
190        * @param Returns the trimmed given parameter (the str instance)
191        * @see #trimEnd(const char *)
192        */
193       static std::string& trimEnd(std::string &str)
194       {
195          if (str.capacity() < 1) return str;
196 
197          int i;
198          for (i=(int)str.length()-1; i >= 0; i--) {
199              if (!isspace(str[i])) {
200                  str = str.substr(0, i+1);
201                  return str;
202              }
203          }
204          if (i<0) str = EMPTY_STRING;
205          return str;
206       }
207       
208 
209       /**
210        * Trims all spaces (like blanks and newlines) at the start and the end of the std::string. 
211        * <pre>
212        * "  \t Hello \t World \n" -> "Hello \t World"
213        * </pre>
214        * @param str The given std::string
215        * @return The trimmed std::string
216        */
217       static std::string trim(const char *str)
218       {
219          std::string buffer = trimStart(str);
220          if (buffer.empty()) return EMPTY_STRING;
221          return trimEnd(buffer.c_str());
222       }
223 
224       /**
225        * @param str The given std::string will be trimmed (in - out parameter)
226        * @param Returns the trimmed given parameter (the str instance)
227        * @see #trim(const char *)
228        */
229       static void trim(std::string &str)
230       {
231          if (str.capacity() < 1 || str.size() < 1) return;
232 
233          int jj=0;
234          if (isspace(str[str.size()-1])) {
235             for (jj=(int)str.size()-2; jj >= 0; jj--) {
236                 if (!isspace(str[jj])) {
237                    str.resize(jj+1);
238                    break;
239                 }
240             }
241          }
242          if (jj<0) {
243             str = EMPTY_STRING;
244             return;
245          }
246 
247          if (!isspace(str[0]))
248             return;
249          for (std::string::size_type ii=1; ii<str.size(); ii++) {
250             if (!isspace(str[ii])) {
251                str = str.substr(ii);
252                return;
253             }
254          }
255       }
256 
257       static std::string trim(const std::string &str) {
258          std::string tmp = str;
259          trim(tmp);
260          return tmp;
261       }
262 
263    };
264 
265 }}} // namespace
266 
267 #endif


syntax highlighted by Code2HTML, v. 0.9.1