1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 ///
18 /// \file gstr.h
19 ///
20 
21 #ifndef G_STR_H
22 #define G_STR_H
23 
24 #include "gdef.h"
25 #include "gexception.h"
26 #include "gstrings.h"
27 #include <string>
28 #include <sstream>
29 #include <iostream>
30 #include <list>
31 #include <vector>
32 
33 /// \namespace G
34 namespace G
35 {
36 	class Str ;
37 }
38 
39 /// \class G::Str
40 /// A static class which provides string helper functions.
41 ///
42 class G::Str
43 {
44 public:
45 	G_EXCEPTION_CLASS( Overflow , "conversion error: over/underflow" ) ;
46 	G_EXCEPTION_CLASS( InvalidFormat, "conversion error: invalid format" ) ;
47 	typedef std::string::size_type size_type ;
48 
49 	static bool replace( std::string & s ,
50 		const std::string & from , const std::string & to ,
51 		size_type * pos_p = NULL ) ;
52 			///< Replaces 'from' with 'to', starting at offset '*pos_p'.
53 			///< Returns true if a substitution was made, and adjusts
54 			///< '*pos_p' by to.length().
55 
56 	static unsigned int replaceAll( std::string & s , const std::string & from , const std::string & to ) ;
57 		///< Does a global replace on string 's', replacing all
58 		///< occurences of sub-string 'from' with 'to'. Returns
59 		///< the number of substitutions made. Consider using
60 		///< in a while loop if 'from' is more than one character.
61 
62 	static unsigned int replaceAll( std::string & s , const char * from , const char * to ) ;
63 		///< A c-string overload, provided for performance reasons.
64 
65 	static void removeAll( std::string & , char ) ;
66 		///< Removes all occurrences of the character from the string.
67 
68 	static void trimLeft( std::string & s , const std::string & ws , size_type limit = 0U ) ;
69 		///< Trims the lhs of s, taking off up to 'limit' of the 'ws' characters.
70 
71 	static void trimRight( std::string & s , const std::string & ws , size_type limit = 0U ) ;
72 		///< Trims the rhs of s, taking off up to 'limit' of the 'ws' characters.
73 
74 	static void trim( std::string & s , const std::string & ws ) ;
75 		///< Trims both ends of s, taking off any of the 'ws' characters.
76 
77 	static std::string trimmed( const std::string & s , const std::string & ws ) ;
78 		///< Returns a trim()med version of s.
79 
80 	static bool isNumeric( const std::string & s , bool allow_minus_sign = false ) ;
81 		///< Returns true if every character is a decimal digit.
82 		///< Empty strings return true.
83 
84 	static bool isPrintableAscii( const std::string & s ) ;
85 		///< Returns true if every character is a 7-bit, non-control
86 		///< character (ie. 0x20<=c<0x7f). Empty strings return true.
87 
88 	static bool isUShort( const std::string & s ) ;
89 		///< Returns true if the string can be converted into
90 		///< an unsigned short without throwing an exception.
91 
92 	static bool isUInt( const std::string & s ) ;
93 		///< Returns true if the string can be converted into
94 		///< an unsigned integer without throwing an exception.
95 
96 	static bool isULong( const std::string & s ) ;
97 		///< Returns true if the string can be converted into
98 		///< an unsigned long without throwing an exception.
99 
100 	static std::string fromBool( bool b ) ;
101 		///< Converts boolean 'b' to a string.
102 
103 	static std::string fromDouble( double d ) ;
104 		///< Converts double 'd' to a string.
105 
106 	static std::string fromInt( int i ) ;
107 		///< Converts int 'i' to a string.
108 
109 	static std::string fromLong( long l ) ;
110 		///< Converts long 'l' to a string.
111 
112 	static std::string fromShort( short s ) ;
113 		///< Converts short 's' to a string.
114 
115 	static std::string fromUInt( unsigned int ui ) ;
116 		///< Converts unsigned int 'ui' to a string.
117 
118 	static std::string fromULong( unsigned long ul ) ;
119 		///< Converts unsigned long 'ul' to a string.
120 
121 	static std::string fromUShort( unsigned short us ) ;
122 		///< Converts unsigned short 'us' to a string.
123 
124 	static bool toBool( const std::string & s ) ;
125 		///< Converts string 's' to a bool.
126 		///<
127 		///< Exception: InvalidFormat
128 
129 	static double toDouble( const std::string & s ) ;
130 		///< Converts string 's' to a double.
131 		///<
132 		///< Exception: Overflow
133 		///< Exception: InvalidFormat
134 
135 	static int toInt( const std::string & s ) ;
136 		///< Converts string 's' to an int.
137 		///<
138 		///< Exception: Overflow
139 		///< Exception: InvalidFormat
140 
141 	static long toLong( const std::string & s ) ;
142 		///< Converts string 's' to a long.
143 		///<
144 		///< Exception: Overflow
145 		///< Exception: InvalidFormat
146 
147 	static short toShort( const std::string & s ) ;
148 		///< Converts string 's' to a short.
149 		///<
150 		///< Exception: Overflow
151 		///< Exception: InvalidFormat
152 
153 	static unsigned int toUInt( const std::string & s , bool limited = false ) ;
154 		///< Converts string 's' to an unsigned int.
155 		///<
156 		///< If 'limited' is true then very large numeric strings
157 		///< are limited to the maximum value of the numeric type,
158 		///< without an Overflow exception.
159 		///<
160 		///< Exception: Overflow
161 		///< Exception: InvalidFormat
162 
163 	static unsigned long toULong( const std::string & s , bool limited = false ) ;
164 		///< Converts string 's' to an unsigned long.
165 		///<
166 		///< If 'limited' is true then very large numeric strings
167 		///< are limited to the maximum value of the numeric type,
168 		///< without an Overflow exception.
169 		///<
170 		///< Exception: Overflow
171 		///< Exception: InvalidFormat
172 
173 	static unsigned short toUShort( const std::string & s , bool limited = false ) ;
174 		///< Converts string 's' to an unsigned short.
175 		///<
176 		///< If 'limited' is true then very large numeric strings
177 		///< are limited to the maximum value of the numeric type,
178 		///< without an Overflow exception.
179 		///<
180 		///< Exception: Overflow
181 		///< Exception: InvalidFormat
182 
183 	static void toUpper( std::string & s ) ;
184 		///< Replaces all lowercase characters in string 's' by
185 		///< uppercase characters.
186 
187 	static void toLower( std::string & s ) ;
188 		///< Replaces all uppercase characters in string 's' by
189 		///< lowercase characters.
190 
191 	static std::string upper( const std::string & s ) ;
192 		///< Returns a copy of 's' in which all lowercase characters
193 		///< have been replaced by uppercase characters.
194 
195 	static std::string lower( const std::string & s ) ;
196 		///< Returns a copy of 's' in which all uppercase characters
197 		///< have been replaced by lowercase characters.
198 
199 	static std::string toPrintableAscii( char c , char escape = '\\' ) ;
200 		///< Returns a 7-bit printable representation of the given input character.
201 
202 	static std::string toPrintableAscii( const std::string & in , char escape = '\\' ) ;
203 		///< Returns a 7-bit printable representation of the given input string.
204 
205 	static std::string toPrintableAscii( const std::wstring & in , wchar_t escape = L'\\' ) ;
206 		///< Returns a 7-bit printable representation of the given wide input string.
207 
208 	static std::string printable( const std::string & in , char escape = '\\' ) ;
209 		///< Returns a printable represention of the given input string.
210 		///< Typically used to prevent escape sequences getting into log files.
211 
212 	static void escape( std::string & , const std::string & specials , char escape = '\\' ) ;
213 		///< Prefixes each occurrence of one of the special characters
214 		///< with the escape character.
215 
216 	static std::string escaped( const std::string & , const std::string & specials , char escape = '\\' ) ;
217 		///< Prefixes each occurrence of one of the special characters
218 		///< with the escape character.
219 
220 	static std::string readLineFrom( std::istream & stream , const std::string & eol = std::string() ) ;
221 		///< Reads a line from the stream using the given line terminator.
222 		///< The line terminator is not part of the returned string.
223 		///< The terminator defaults to the newline.
224 		///<
225 		///< Note that alternatives in the standard library such as
226 		///< std::istream::getline() or std::getline(stream,string)
227 		///< in the standard "string" header are limited to a single
228 		///< character as the terminator.
229 		///<
230 		///< The stream's fail bit is set if (1) an empty string was
231 		///< returned because the stream was already at eof or (2)
232 		///< the string overflowed. Therefore, ignoring overflow, if
233 		///< the stream ends in an incomplete line that line fragment
234 		///< is returned with the stream's eof flag set but the fail bit
235 		///< reset and the next attempted read will return an empty string
236 		///< with the fail bit set. If the stream ends with a complete
237 		///< line then the last line is returned with eof and fail
238 		///< bits reset and the next attempted read will return
239 		///< an empty string with eof and fail bits set.
240 		///<
241 		///< If we don't worry too much about the 'bad' state and note that
242 		///< the boolean tests on a stream test its 'fail' flag (not eof)
243 		///< we can use a read loop like "while(s.good()){read(s);if(s)...}".
244 
245 	static void readLineFrom( std::istream & stream , const std::string & eol , std::string & result ,
246 		bool pre_erase_result = true ) ;
247 			///< An overload which avoids string copying.
248 
249 	static std::string wrap( std::string text ,
250 		const std::string & prefix_first_line , const std::string & prefix_subsequent_lines ,
251 		size_type width = 70U ) ;
252 			///< Does word-wrapping. The return value is a string with
253 			///< embedded newlines.
254 
255 	static void splitIntoTokens( const std::string & in , Strings & out , const std::string & ws ) ;
256 		///< Splits the string into 'ws'-delimited tokens. The
257 		///< behaviour is like strtok() in that adjacent delimiters
258 		///< count as one and leading and trailing delimiters are ignored.
259 		///< Ths output array is cleared first.
260 
261 	static void splitIntoTokens( const std::string & in , StringArray & out , const std::string & ws ) ;
262 		///< Overload for vector<string>.
263 
264 	static void splitIntoFields( const std::string & in , Strings & out ,
265 		const std::string & seperators , char escape = '\0' ,
266 		bool discard_bogus_escapes = true ) ;
267 			///< Splits the string into fields. Duplicated, leading
268 			///< and trailing separator characters are all significant.
269 			///< Ths output array is cleared first.
270 			///<
271 			///< If a non-null escape character is given then any escaped
272 			///< separator is not used for splitting. If the 'discard...'
273 			///< parameter is true then escapes will never appear in the
274 			///< output except for where there were originally double escapes.
275 			///< This is the preferred behaviour but it can create problems
276 			///< if doing nested splitting -- the escapes are lost by the
277 			///< time the sub-strings are split.
278 
279 	static void splitIntoFields( const std::string & in , StringArray & out ,
280 		const std::string & seperators , char escape = '\0' , bool discard_bogus_escapes = true ) ;
281 			///< Overload for vector<string>.
282 
283 	static std::string join( const Strings & strings , const std::string & sep ) ;
284 		///< Concatenates a set of strings.
285 
286 	static std::string join( const StringArray & strings , const std::string & sep ) ;
287 		///< Concatenates a set of strings.
288 
289 	static Strings keys( const StringMap & string_map ) ;
290 		///< Extracts the keys from a map of strings.
291 
292 	static std::string head( const std::string & in , std::string::size_type pos ,
293 		const std::string & default_ = std::string() ) ;
294 			///< Returns the first part of the string up to just before the given position.
295 			///< The character at pos is not returned. Returns the supplied default
296 			///< if pos is npos.
297 
298 	static std::string tail( const std::string & in , std::string::size_type pos ,
299 		const std::string & default_ = std::string() ) ;
300 			///< Returns the last part of the string after the given position.
301 			///< The character at pos is not returned. Returns the supplied default
302 			///< if pos is npos.
303 
304 	static bool tailMatch( const std::string & in , const std::string & ending ) ;
305 		///< Returns true if the given string has the given ending.
306 
307 	static std::string ws() ;
308 		///< A convenience function returning standard whitespace characters.
309 
310 private:
311 	static void readLineFromImp( std::istream & , const std::string & , std::string & ) ;
312 	Str() ; // not implemented
313 } ;
314 
315 #endif
316