implement iterator based join_string()
[libi2ncommon] / src / stringfunc.hxx
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /** @file
21  * @brief collection of string tools (/ functions).
22  *
23  * contains a collection of miscellaneous functions for dealing with strings.
24  *
25  * some functions (like trim, lower case, upper case ...) are available in two versions:
26  * - a modifying one (suffix "Mod") which modifies the given string argument in place.
27  * - a non modifying one which take a constant string reference and returns a new string.
28  * .
29  *
30  *
31  * (c) Copyright 2007-2008 by Intra2net AG
32  */
33
34 #ifndef __STRINGFUNC_HXX
35 #define __STRINGFUNC_HXX
36
37 #include <stdio.h>
38 #include <list>
39 #include <numeric>
40 #include <set>
41 #include <vector>
42 #include <string>
43 #include <sstream>
44 #include <stdexcept>
45 #include <sys/types.h>
46
47 namespace I2n
48 {
49
50 /*
51 ** some useful constants:
52 */
53
54 extern const std::string Whitespaces;
55 extern const std::string LineEndings;
56
57
58 /*
59 ** predicates:
60 */
61
62
63 bool has_prefix(const std::string& str, const std::string& prefix);
64
65 bool has_suffix(const std::string& str, const std::string& suffix);
66
67
68 /*
69 ** tool functions(modifying):
70 */
71
72 std::string trim_mod(std::string& str, const std::string& charlist = Whitespaces);
73
74 std::string chomp_mod(std::string& str, const std::string& what= LineEndings );
75
76 std::string to_lower_mod(std::string& str);
77
78 std::string to_upper_mod(std::string& str);
79
80
81 /*
82 ** tool functions (not modifying):
83 */
84
85 std::string trim(const std::string& str, const std::string& charlist = Whitespaces);
86
87 std::string chomp(const std::string& str, const std::string& what= LineEndings );
88
89 std::string to_lower(const std::string& str);
90
91 std::string to_upper(const std::string& str);
92
93
94 std::string remove_suffix(const std::string& str, const std::string& suffix);
95
96 std::string remove_prefix(const std::string& str, const std::string& prefix);
97
98
99
100 /*
101 ** split and join:
102 */
103
104
105 bool pair_split(
106    const std::string& str,
107    std::string& key,
108    std::string& value,
109    char delimiter = '=');
110
111
112 void split_string(
113    const std::string& str,
114    std::list< std::string >& result,
115    const std::string& delimiter= "\n",
116    bool omit_empty= false,
117    const std::string& trim_list= std::string()
118 );
119
120 void split_string(
121    const std::string& str,
122    std::vector< std::string >& result,
123    const std::string& delimiter= "\n",
124    bool omit_empty= false,
125    const std::string& trim_list= std::string()
126 );
127
128 std::list< std::string > split_string(
129    const std::string& str,
130    const std::string& delimiter = "\n",
131    bool omit_empty= false,
132    const std::string& trim_list= std::string()
133 );
134
135 struct concatenator {
136     std::string delim;
137
138     concatenator (const std::string &delim) : delim (delim) { }
139
140     inline std::string operator() (const std::string &acc, const std::string &elt) const
141     { return acc + delim + elt; }
142 };
143
144 template<typename Iter>
145 std::string
146 join_string (
147     Iter first,
148     Iter last,
149     const std::string &delimiter = "\n"
150 )
151 {
152     if (first == last) { return ""; }
153
154     const std::string &init = *first++;
155     if (first == last) { return init; }
156
157     return std::accumulate (first, last, init, concatenator (delimiter));
158 }
159
160 /**
161  * @brief joins a container of strings into a single string.
162  *
163  * This funtion is (basically) the reverse operation of @a split_string.
164  *
165  * @param parts         the container of strings.
166  * @param delimiter     the delimiter to insert between the strings.
167  * @return              the joined string.
168  */
169 template<typename Cont>
170 inline std::string join_string(
171    const Cont& parts,
172    const std::string& delimiter = "\n"
173 )
174 { return join_string (parts.begin (), parts.end (), delimiter); }
175
176 std::string join_string(
177    const char *const parts [],
178    const std::string& delimiter = "\n"
179 );
180
181
182 /*
183 ** conversions:
184 */
185
186
187 std::string convert_binary_to_hex(const std::string&str, bool upper_case_digits= false);
188
189 std::string convert_hex_to_binary(const std::string& str) throw(std::runtime_error);
190
191
192 /*
193 ** "type conversions":
194 */
195
196
197 /**
198  * convert a datatype @a T to a string via string stream.
199  *
200  * This will not report trouble in conversion; for example:
201  *     string_to<int>("christian")
202  * will return 0 and not throw an error.
203  * Use boost::lexical_cast<T>(string) to get error-checked results.
204  *
205  * @param s the string which should be converted to @a T.
206  * @return the value of type T.
207  */
208 template<
209 class T
210 >
211 T string_to(const std::string& s)
212 {
213    std::istringstream istr(s);
214    T result;
215    istr >> result;
216    return result;
217 } // eo string_to(const std::string&)
218
219
220 /**
221  * convert a datatype @a T to a string via string stream.
222  *
223  * @param s the string which should be converted to @a T.
224  * @param result the resulting value of type @a T.
225  * @return @a true iff the internal string stream was EOF after the conversion.
226  *
227  * @attention: does not return if the conversion was successful. So check for empty strings before.
228  */
229 template<
230 class T
231 >
232 bool string_to(const std::string& s, T& result)
233 {
234    std::istringstream istr(s);
235    istr >> result;
236    return istr.eof();
237 } // eo string_to(const std::string&)
238
239
240 /**
241  * convert string in hexadecimal notation to a datatype @a T
242  * supports strings with and without "0x" notation, e.g. 0xff and FF are both valid
243  * 
244  * @param s the hex string which should be converted to @a T.
245  * @return the value of type T.
246  */
247 template<
248 class T
249 >
250 T hex_string_to(const std::string& s)
251 {
252    std::istringstream istr(s);
253    T result;
254    istr >> std::hex >> result;
255    return result;
256 } // eo string_to(const std::string&)
257
258
259 /**
260  * convert string in hexadecimal notation to a datatype @a T
261  * supports strings with and without "0x" notation, e.g. 0xff and FF are both valid
262  *
263  * @param s the hex string which should be converted to @a T.
264  * @param result the resulting value of type @a T.
265  * @return @a true iff the internal string stream was EOF after the conversion.
266  *
267  * @attention: does not return if the conversion was successful. So check for empty strings before.
268  */
269 template<
270 class T
271 >
272 bool hex_string_to(const std::string& s, T& result)
273 {
274    std::istringstream istr(s);
275    istr >> std::hex >> result;
276    return istr.eof();
277 } // eo string_to(const std::string&)
278
279
280 /**
281  * convert a string to another datatype @a T via string stream.
282  *
283  * @param v the value (of type @a T) which should be converted to a string.
284  * @return the resulting string.
285  */
286 template<
287 class T
288 >
289 std::string to_string(const T& v)
290 {
291    std::ostringstream ostr;
292    ostr << v;
293    return ostr.str();
294 } // eo to_string(const T&)
295
296
297 /**
298  * Create a string with types shortened in texts describing C++ types
299  *
300  * for example: std::list<some_long_type, std::allocator<some_long_type> >
301  * -->  std::list<some_long_type, _alloc_>
302  *
303  * and std::basic_string<char, std::char_traits<char>, std::allocator<char> >
304  * --> std::string
305  */
306 std::string shorten_stl_types(const std::string &input);
307
308 std::string base64_encode(const std::string &input, bool one_line=true);
309 std::string base64_decode(const std::string &input, bool one_line=true);
310
311 } // eo namespace I2n
312
313
314 #if 0
315 std::string to_lower(const std::string &src);
316 std::string to_upper(const std::string &src);
317 #else
318 // compatibility: import lower/upper funcs from I2n:
319 using I2n::to_lower;
320 using I2n::to_upper;
321 #endif
322
323
324 enum UnitBase {
325     UnitBase1000, // SI decimal, composed by multiples of 1000 (KB, MB, etc.)
326     UnitBase1024 // IEC binary, composed by multiples of 1024 (KiB, MiB, etc. )
327 };
328
329 enum UnitFormat {
330     ShortUnitFormat, // B, KB, MB, ...
331     LongUnitFormat // Byte, KByte, MByte, ...
332 };
333
334 std::string nice_unit_format(
335         const int64_t input,
336         const UnitFormat format = ShortUnitFormat,
337         const UnitBase base = UnitBase1024
338 );
339
340 std::string nice_unit_format(
341         const double input,
342         const UnitFormat format = ShortUnitFormat,
343         const UnitBase base = UnitBase1024
344 );
345
346 bool replace_all(std::string &base, const std::string *ist, const std::string *soll);
347 bool replace_all(std::string &base, const char *ist, const char *soll);
348 bool replace_all(std::string &base, const char *ist, const std::string *soll);
349 bool replace_all(std::string &base, const std::string &ist, const char *soll);
350 bool replace_all(std::string &base, const std::string &ist, const std::string &soll);
351
352 std::string iso_to_utf8(const std::string& isostring);
353 std::string utf8_to_iso(const std::string& utf8string);
354 std::string utf7imap_to_utf8(const std::string &utf7imapstring);
355 std::string utf8_to_utf7imap(const std::string &utf8string);
356
357 std::string strip_html_tags(const std::string &input);
358 std::string smart_html_entities(const std::string &input);
359 std::string html_entities(std::string str);
360 std::string html_entities_to_console(std::string str);
361
362 typedef std::pair<std::string::size_type, std::string::size_type> CommentZone;
363 std::vector<CommentZone> find_html_comments(const std::string &str);
364 void remove_html_comments(std::string &str);
365 void remove_html_comments(std::string &str, const std::vector<CommentZone> &comments);
366
367 std::string sanitize_for_logging(const std::string &str, const char replace_with='?');
368
369 std::string escape(const std::string &s);
370
371 std::string descape(const std::string &s, int startpos, int &endpos);
372 inline std::string descape(const std::string &s)
373 {
374    int endpos;
375    return descape(s,0,endpos);
376 }
377
378 std::string escape_shellarg(const std::string &input);
379
380 #endif