2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
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.
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.
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.
22 * (c) Copyright 2007-2008 by Intra2net AG
30 #include <cmath> // for round()
37 #include <boost/numeric/conversion/cast.hpp>
39 #include <stringfunc.hxx>
50 const std::string hexDigitsLower("0123456789abcdef");
51 const std::string hexDigitsUpper("0123456789ABCDEF");
56 char operator() (char c)
58 return std::toupper(c);
60 }; // eo struct UpperFunc
65 char operator() (char c)
67 return std::tolower(c);
69 }; // eo struct LowerFunc
72 } // eo namespace <anonymous>
77 * default list of Whitespaces (" \t\r\n");
79 const std::string Whitespaces = " \t\r\n";
82 * default list of lineendings ("\r\n");
84 const std::string LineEndings= "\r\n";
89 * @brief checks if a string begins with a given prefix.
90 * @param[in,out] str the string which is tested
91 * @param prefix the prefix which should be tested for.
92 * @return @a true iff the prefix is not empty and the string begins with that prefix.
94 bool has_prefix(const std::string& str, const std::string& prefix)
96 if (prefix.empty() || str.empty() || str.size() < prefix.size() )
100 return str.compare(0, prefix.size(), prefix) == 0;
101 } // eo has_prefix(const std::string&,const std::string&)
105 * @brief checks if a string ends with a given suffix.
106 * @param[in,out] str the string which is tested
107 * @param suffix the suffix which should be tested for.
108 * @return @a true iff the suffix is not empty and the string ends with that suffix.
110 bool has_suffix(const std::string& str, const std::string& suffix)
112 if (suffix.empty() || str.empty() || str.size() < suffix.size() )
116 return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
117 } // eo has_suffix(const std::string&,const std::string&)
121 * cut off characters from a given list from front and end of a string.
122 * @param[in,out] str the string which should be trimmed.
123 * @param charlist the list of characters to remove from beginning and end of string
124 * @return the result string.
126 std::string trim_mod(std::string& str, const std::string& charlist)
128 // first: trim the beginning:
129 std::string::size_type pos= str.find_first_not_of (charlist);
130 if (pos == std::string::npos)
132 // whole string consists of charlist (or is already empty)
138 // str starts with charlist
141 // now let's look at the tail:
142 pos= str.find_last_not_of(charlist) +1; // note: we already know there is at least one other char!
143 if ( pos < str.size() )
145 str.erase(pos, str.size()-pos);
148 } // eo trim_mod(std::string&,const std::string&)
153 * removes last character from a string when it is in a list of chars to be removed.
154 * @param[in,out] str the string.
155 * @param what the list of chars which will be tested for.
156 * @return the resulting string with last char removed (if applicable)
158 std::string chomp_mod(std::string& str, const std::string& what)
160 if (str.empty() || what.empty() )
164 if (what.find(str.at (str.size()-1) ) != std::string::npos)
166 str.erase(str.size() - 1);
169 } // eo chomp_mod(std::string&,const std::string&)
173 * @brief converts a string to lower case.
174 * @param[in,out] str the string to modify.
177 std::string to_lower_mod(std::string& str)
179 std::transform(str.begin(), str.end(), str.begin(), LowerFunc() );
181 } // eo to_lower_mod(std::string&)
185 * @brief converts a string to upper case.
186 * @param[in,out] str the string to modify.
189 std::string to_upper_mod(std::string& str)
191 std::transform( str.begin(), str.end(), str.begin(), UpperFunc() );
193 } // eo to_upper_mod(std::string&)
198 * cut off characters from a given list from front and end of a string.
199 * @param str the string which should be trimmed.
200 * @param charlist the list of characters to remove from beginning and end of string
201 * @return the result string.
203 std::string trim (const std::string& str, const std::string& charlist)
205 // first: trim the beginning:
206 std::string::size_type pos0= str.find_first_not_of(charlist);
207 if (pos0 == std::string::npos)
209 // whole string consists of charlist (or is already empty)
210 return std::string();
212 // now let's look at the end:
213 std::string::size_type pos1= str.find_last_not_of(charlist);
214 return str.substr(pos0, pos1 - pos0 + 1);
215 } // eo trim(const std:.string&,const std::string&)
219 * removes last character from a string when it is in a list of chars to be removed.
220 * @param str the string.
221 * @param what the list of chars which will be tested for.
222 * @return the resulting string with last char removed (if applicable)
224 std::string chomp (const std::string& str, const std::string& what)
226 if (str.empty() || what.empty() )
230 if (what.find(str.at (str.size()-1) ) != std::string::npos)
232 return str.substr(0, str.size()-1);
235 } // eo chomp(const std:.string&,const std::string&)
239 * @brief returns a lower case version of a given string.
240 * @param str the string
241 * @return the lower case version of the string
243 std::string to_lower (const std::string& str)
245 std::string result(str);
246 return to_lower_mod(result);
247 } // eo to_lower(const std::string&)
251 * @brief returns a upper case version of a given string.
252 * @param str the string
253 * @return the upper case version of the string
255 std::string to_upper(const std::string& str)
257 std::string result(str);
258 return to_upper_mod(result);
259 } // eo to_upper(const std::string&)
264 * @brief removes a given suffix from a string.
265 * @param str the string.
266 * @param suffix the suffix which should be removed if the string ends with it.
267 * @return the string without the suffix.
269 * If the string ends with the suffix, it is removed. If the the string doesn't end
270 * with the suffix the original string is returned.
272 std::string remove_suffix(const std::string& str, const std::string& suffix)
274 if (has_suffix(str,suffix) )
276 return str.substr(0, str.size()-suffix.size() );
279 } // eo remove_suffix(const std::string&,const std::string&)
284 * @brief removes a given prefix from a string.
285 * @param str the string.
286 * @param prefix the prefix which should be removed if the string begins with it.
287 * @return the string without the prefix.
289 * If the string begins with the prefix, it is removed. If the the string doesn't begin
290 * with the prefix the original string is returned.
292 std::string remove_prefix(const std::string& str, const std::string& prefix)
294 if (has_prefix(str,prefix) )
296 return str.substr( prefix.size() );
299 } // eo remove_prefix(const std::string&,const std::string&)
303 * split a string to key and value delimited by a given delimiter.
304 * The resulting key and value strings are trimmed (Whitespaces removed at beginning and end).
305 * @param str the string which should be splitted.
306 * @param[out] key the resulting key
307 * @param[out] value the resulting value
308 * @param delimiter the delimiter between key and value; default is '='.
309 * @return @a true if the split was successful.
312 const std::string& str,
317 std::string::size_type pos = str.find (delimiter);
318 if (pos == std::string::npos) return false;
319 key= str.substr(0,pos);
320 value= str.substr(pos+1);
324 } // eo pair_split(const std::string&,std::string&,std::string&,char)
328 * splits a string by given delimiter
330 * @param[in] str the string which should be splitted.
331 * @param[out] result the list resulting from splitting @a str.
332 * @param[in] delimiter the delimiter (word/phrase) at which @a str should be splitted.
333 * @param[in] omit_empty should empty parts not be stored?
334 * @param[in] trim_list list of characters the parts should be trimmed by.
335 * (empty string results in no trim)
338 const std::string& str,
339 std::list<std::string>& result,
340 const std::string& delimiter,
342 const std::string& trim_list
345 std::string::size_type pos, last_pos=0;
346 bool delimiter_found= false;
347 while ( last_pos < str.size() && last_pos != std::string::npos)
349 pos= str.find(delimiter, last_pos);
351 if (pos == std::string::npos)
353 part= str.substr(last_pos);
354 delimiter_found= false;
358 part= str.substr(last_pos, pos-last_pos);
359 delimiter_found=true;
361 if (pos != std::string::npos)
363 last_pos= pos+ delimiter.size();
367 last_pos= std::string::npos;
369 if (!trim_list.empty() ) trim_mod (part, trim_list);
370 if (omit_empty && part.empty() ) continue;
371 result.push_back( part );
373 // if the string ends with a delimiter we need to append an empty string if no omit_empty
375 // (this way we keep the split result consistent to a join operation)
376 if (delimiter_found && !omit_empty)
378 result.push_back("");
380 } // eo split_string(const std::string&,std::list< std::string >&,const std::string&,bool,const std::string&)
383 /** call split_string with list<string>, converts result to vector; vector is clear()-ed first
385 * Note: Uses 3 O(n)-operations: list.size, vector.resize and std::swap_ranges;
386 * not sure whether there is a better way to do this
389 const std::string& str,
390 std::vector<std::string>& result,
391 const std::string& delimiter,
393 const std::string& trim_list
396 std::list<std::string> tmp;
397 split_string(str, tmp, delimiter, omit_empty, trim_list);
398 std::size_t size = tmp.size(); // this is O(n)
400 result.resize(size); // also O(n)
401 std::swap_ranges(tmp.begin(), tmp.end(), result.begin()); // also O(n)
405 * splits a string by a given delimiter
406 * @param str the string which should be splitted.
407 * @param delimiter delimiter the delimiter (word/phrase) at which @a str should be splitted.
408 * @param[in] omit_empty should empty parts not be stored?
409 * @param[in] trim_list list of characters the parts should be trimmed by.
410 * (empty string results in no trim)
411 * @return the list resulting from splitting @a str.
413 std::list<std::string> split_string(
414 const std::string& str,
415 const std::string& delimiter,
417 const std::string& trim_list
420 std::list<std::string> result;
421 split_string(str, result, delimiter, omit_empty, trim_list);
423 } // eo split_string(const std::string&,const std::string&,bool,const std::string&)
427 * @brief joins a list of strings into a single string.
429 * This funtion is (basically) the reverse operation of @a split_string.
431 * @param parts the list of strings.
432 * @param delimiter the delimiter which is inserted between the strings.
433 * @return the joined string.
435 std::string join_string(
436 const std::list< std::string >& parts,
437 const std::string& delimiter
441 if (! parts.empty() )
443 std::list< std::string >::const_iterator it= parts.begin();
445 while ( ++it != parts.end() )
452 } // eo join_string(const std::list< std::string >&,const std::string&)
455 /** @brief same as join_string for list, except uses a vector */
456 std::string join_string(
457 const std::vector< std::string >& parts,
458 const std::string& delimiter
462 if (! parts.empty() )
464 std::vector< std::string >::const_iterator it= parts.begin();
466 while ( ++it != parts.end() )
473 } // eo join_string(const std::vector< std::string >&,const std::string&)
483 * @brief returns a hex string from a binary string.
484 * @param str the (binary) string
485 * @param upper_case_digits determine whether to use upper case characters for digits A-F.
486 * @return the string in hex notation.
488 std::string convert_binary_to_hex(
489 const std::string& str,
490 bool upper_case_digits
494 std::string hexDigits(upper_case_digits ? hexDigitsUpper : hexDigitsLower);
495 for ( std::string::const_iterator it= str.begin();
499 result.push_back( hexDigits[ ( (*it) >> 4) & 0x0f ] );
500 result.push_back( hexDigits[ (*it) & 0x0f ] );
503 } // eo convert_binary_to_hex(const std::string&,bool)
507 * @brief converts a hex digit string to binary string.
508 * @param str hex digit string
509 * @return the binary string.
511 * The hex digit string may contains white spaces or colons which are treated
512 * as delimiters between hex digit groups.
514 * @todo rework the handling of half nibbles (consistency)!
516 std::string convert_hex_to_binary(
517 const std::string& str
519 throw (std::runtime_error)
523 bool hasNibble= false;
524 bool lastWasWS= true;
525 for ( std::string::const_iterator it= str.begin();
529 std::string::size_type p = hexDigitsLower.find( *it );
530 if (p== std::string::npos)
532 p= hexDigitsUpper.find( *it );
534 if (p == std::string::npos)
536 if ( ( Whitespaces.find( *it ) != std::string::npos) // is it a whitespace?
537 or ( *it == ':') // or a colon?
540 // we treat that as a valid delimiter:
543 // 1 nibble before WS is treate as lower part:
552 if (p == std::string::npos )
554 throw runtime_error("illegal character in hex digit string: " + str);
568 //we already had a nibble, so a char is complete now:
569 result.push_back( c );
574 // this is the first nibble of a new char:
580 //well, there is one nibble left
581 // let's do some heuristics:
584 // if the preceeding character was a white space (or a colon)
585 // we treat the nibble as lower part:
586 //( this is consistent with shortened hex notations where leading zeros are not noted)
587 result.push_back( c );
591 // if it was part of a hex digit chain, we treat it as UPPER part (!!)
592 result.push_back( c << 4 );
596 } // eo convert_hex_to_binary(const std::string&)
599 } // eo namespace I2n
604 std::string iso_to_utf8(const std::string& isostring)
608 iconv_t i2utf8 = iconv_open("UTF-8", "ISO-8859-1");
610 if (iso_to_utf8 == (iconv_t)-1)
611 throw runtime_error("iconv can't convert from ISO-8859-1 to UTF-8");
613 size_t in_size=isostring.size();
614 size_t out_size=in_size*4;
616 char *buf = (char *)malloc(out_size+1);
618 throw runtime_error("out of memory for iconv buffer");
620 char *in = (char *)isostring.c_str();
622 iconv(i2utf8, &in, &in_size, &out, &out_size);
624 buf[isostring.size()*4-out_size]=0;
634 std::string utf8_to_iso(const std::string& utf8string)
638 iconv_t utf82iso = iconv_open("ISO-8859-1","UTF-8");
640 if (utf82iso == (iconv_t)-1)
641 throw runtime_error("iconv can't convert from UTF-8 to ISO-8859-1");
643 size_t in_size=utf8string.size();
644 size_t out_size=in_size;
646 char *buf = (char *)malloc(out_size+1);
648 throw runtime_error("out of memory for iconv buffer");
650 char *in = (char *)utf8string.c_str();
652 iconv(utf82iso, &in, &in_size, &out, &out_size);
654 buf[utf8string.size()-out_size]=0;
659 iconv_close(utf82iso);
664 wchar_t* utf8_to_wbuf(const std::string& utf8string)
666 iconv_t utf82wstr = iconv_open("UCS-4LE","UTF-8");
668 if (utf82wstr == (iconv_t)-1)
669 throw runtime_error("iconv can't convert from UTF-8 to UCS-4");
671 size_t in_size=utf8string.size();
672 size_t out_size= (in_size+1)*sizeof(wchar_t);
674 wchar_t *buf = (wchar_t *)malloc(out_size);
676 throw runtime_error("out of memory for iconv buffer");
678 char *in = (char *)utf8string.c_str();
679 char *out = (char*) buf;
680 if (iconv(utf82wstr, &in, &in_size, &out, &out_size) == (size_t)-1)
681 throw runtime_error("error converting char encodings");
683 buf[ ( (utf8string.size()+1)*sizeof(wchar_t)-out_size) /sizeof(wchar_t) ]=0;
685 iconv_close(utf82wstr);
690 std::string utf7imap_to_utf8(const std::string& utf7imapstring)
694 iconv_t utf7imap2utf8 = iconv_open("UTF-8","UTF-7-IMAP");
696 if (utf7imap2utf8 == (iconv_t)-1)
697 throw runtime_error("iconv can't convert from UTF-7-IMAP to UTF-8");
699 size_t in_size=utf7imapstring.size();
700 size_t out_size=in_size*4;
702 char *buf = (char *)malloc(out_size+1);
704 throw runtime_error("out of memory for iconv buffer");
706 char *in = (char *)utf7imapstring.c_str();
708 iconv(utf7imap2utf8, &in, &in_size, &out, &out_size);
710 buf[utf7imapstring.size()*4-out_size]=0;
715 iconv_close(utf7imap2utf8);
720 std::string utf8_to_utf7imap(const std::string& utf8string)
724 iconv_t utf82utf7imap = iconv_open("UTF-7-IMAP", "UTF-8");
726 if (utf82utf7imap == (iconv_t)-1)
727 throw runtime_error("iconv can't convert from UTF-7-IMAP to UTF-8");
729 // UTF-7 is base64 encoded, a buffer 10x as large
730 // as the utf-8 buffer should be enough. If not the string will be truncated.
731 size_t in_size=utf8string.size();
732 size_t out_size=in_size*10;
734 char *buf = (char *)malloc(out_size+1);
736 throw runtime_error("out of memory for iconv buffer");
738 char *in = (char *)utf8string.c_str();
740 iconv(utf82utf7imap, &in, &in_size, &out, &out_size);
742 buf[utf8string.size()*10-out_size]= 0;
747 iconv_close(utf82utf7imap);
752 // Tokenize string by (html) tags
753 void tokenize_by_tag(vector<pair<string,bool> > &tokenized, const std::string &input)
755 string::size_type pos, len = input.size();
756 bool inside_tag = false;
759 for (pos = 0; pos < len; pos++)
761 if (input[pos] == '<')
765 if (!current.empty() )
767 tokenized.push_back( make_pair(current, false) );
771 current += input[pos];
773 else if (input[pos] == '>' && inside_tag)
775 current += input[pos];
777 if (!current.empty() )
779 tokenized.push_back( make_pair(current, true) );
784 current += input[pos];
787 // String left over in buffer?
788 if (!current.empty() )
789 tokenized.push_back( make_pair(current, false) );
790 } // eo tokenize_by_tag
793 std::string strip_html_tags(const std::string &input)
795 // Pair first: string, second: isTag
796 vector<pair<string,bool> > tokenized;
797 tokenize_by_tag (tokenized, input);
800 vector<pair<string,bool> >::const_iterator token, tokens_end = tokenized.end();
801 for (token = tokenized.begin(); token != tokens_end; ++token)
803 output += token->first;
806 } // eo strip_html_tags
809 // Smart-encode HTML en
810 string smart_html_entities(const std::string &input)
812 // Pair first: string, second: isTag
813 vector<pair<string,bool> > tokenized;
814 tokenize_by_tag (tokenized, input);
817 vector<pair<string,bool> >::const_iterator token, tokens_end = tokenized.end();
818 for (token = tokenized.begin(); token != tokens_end; ++token)
820 // keep HTML tags as they are
822 output += token->first;
824 output += html_entities(token->first);
831 string::size_type find_8bit(const std::string &str)
833 string::size_type l=str.size();
834 for (string::size_type p=0; p < l; p++)
835 if (static_cast<unsigned char>(str[p]) > 127)
841 // encoded UTF-8 chars into HTML entities
842 string html_entities(std::string str)
845 replace_all (str, "&", "&");
846 replace_all (str, "<", "<");
847 replace_all (str, ">", ">");
848 replace_all (str, "\"", """);
849 replace_all (str, "'", "'");
850 replace_all (str, "/", "/");
853 replace_all (str, "\xC3\xA4", "ä");
854 replace_all (str, "\xC3\xB6", "ö");
855 replace_all (str, "\xC3\xBC", "ü");
856 replace_all (str, "\xC3\x84", "Ä");
857 replace_all (str, "\xC3\x96", "Ö");
858 replace_all (str, "\xC3\x9C", "Ü");
861 replace_all (str, "\xC3\x9F", "ß");
863 // conversion of remaining non-ASCII chars needed?
864 // just do if needed because of performance
865 if (find_8bit(str) != string::npos)
867 // convert to fixed-size encoding UTF-32
868 wchar_t* wbuf=utf8_to_wbuf(str);
869 ostringstream target;
871 // replace all non-ASCII chars with HTML representation
872 for (int p=0; wbuf[p] != 0; p++)
874 unsigned int c=wbuf[p];
877 target << static_cast<unsigned char>(c);
879 target << "&#" << c << ';';
888 } // eo html_entities(std::string)
890 // convert HTML entities to something that can be viewed on a basic text console (restricted to ASCII-7)
891 string html_entities_to_console(std::string str)
894 replace_all (str, "&", "&");
895 replace_all (str, "<", "<");
896 replace_all (str, ">", ">");
897 replace_all (str, """, "\"");
898 replace_all (str, "'", "'");
899 replace_all (str, "/", "/");
902 replace_all (str, "ä", "ae");
903 replace_all (str, "ö", "oe");
904 replace_all (str, "ü", "ue");
905 replace_all (str, "Ä", "Ae");
906 replace_all (str, "Ö", "Oe");
907 replace_all (str, "Ü", "Ue");
910 replace_all (str, "ß", "ss");
915 bool replace_all(string &base, const char *ist, const char *soll)
919 return replace_all(base,&i,&s);
922 bool replace_all(string &base, const string &ist, const char *soll)
925 return replace_all(base,&ist,&s);
928 bool replace_all(string &base, const string *ist, const string *soll)
930 return replace_all(base,*ist,*soll);
933 bool replace_all(string &base, const char *ist, const string *soll)
936 return replace_all(base,&i,soll);
939 bool replace_all(string &base, const string &ist, const string &soll)
941 bool found_ist = false;
942 string::size_type a=0;
945 throw runtime_error ("replace_all called with empty search string");
947 while ( (a=base.find(ist,a) ) != string::npos)
949 base.replace(a,ist.size(),soll);
958 * @brief replaces all characters that could be problematic or impose a security risk when being logged
959 * @param str the original string
960 * @param replace_with the character to replace the unsafe chars with
961 * @return a string that is safe to send to syslog or other logfiles
963 * All chars between 0x20 (space) and 0x7E (~) (including) are considered safe for logging.
964 * See e.g. RFC 5424, section 8.2 or the posix character class "printable".
965 * This eliminates all possible problems with NUL, control characters, 8 bit chars, UTF8.
968 std::string sanitize_for_logging(const std::string &str, const char replace_with)
970 std::string output=str;
972 const string::size_type len = output.size();
973 for (std::string::size_type p=0; p < len; p++)
974 if (output[p] < 0x20 || output[p] > 0x7E)
975 output[p]=replace_with;
981 string to_lower(const string &src)
985 string::size_type pos, end = dst.size();
986 for (pos = 0; pos < end; pos++)
987 dst[pos] = tolower(dst[pos]);
992 string to_upper(const string &src)
996 string::size_type pos, end = dst.size();
997 for (pos = 0; pos < end; pos++)
998 dst[pos] = toupper(dst[pos]);
1004 const int MAX_UNIT_FORMAT_SYMBOLS = 6;
1006 const string shortUnitFormatSymbols[MAX_UNIT_FORMAT_SYMBOLS] = {
1015 const string longUnitFormatSymbols[MAX_UNIT_FORMAT_SYMBOLS] = {
1016 i18n_noop(" Bytes"),
1017 i18n_noop(" KBytes"),
1018 i18n_noop(" MBytes"),
1019 i18n_noop(" GBytes"),
1020 i18n_noop(" TBytes"),
1021 i18n_noop(" PBytes")
1025 long double rounding_upwards(
1026 const long double number,
1027 const int rounding_multiplier
1030 long double rounded_number;
1031 rounded_number = number * rounding_multiplier;
1032 rounded_number += 0.5;
1033 rounded_number = (int64_t) (rounded_number);
1034 rounded_number = (long double) (rounded_number) / (long double) (rounding_multiplier);
1036 return rounded_number;
1040 string nice_unit_format(
1041 const int64_t input,
1042 const UnitFormat format,
1046 // select the system of units (decimal or binary)
1048 if (base == UnitBase1000)
1057 long double size = input;
1059 // check the size of the input number to fit in the appropriate symbol
1061 while (size > multiple)
1063 size = size / multiple;
1066 // rollback to the previous values and stop the loop when cannot
1067 // represent the number length.
1068 if (sizecount >= MAX_UNIT_FORMAT_SYMBOLS)
1070 size = size * multiple;
1076 // round the input number "half up" to multiples of 10
1077 const int rounding_multiplier = 10;
1078 size = rounding_upwards(size, rounding_multiplier);
1080 // format the input number, placing the appropriate symbol
1082 out.setf (ios::fixed);
1083 if (format == ShortUnitFormat)
1086 out << size << i18n( shortUnitFormatSymbols[sizecount].c_str() );
1091 out << size << i18n( longUnitFormatSymbols[sizecount].c_str() );
1095 } // eo nice_unit_format(int input)
1098 string nice_unit_format(
1100 const UnitFormat format,
1104 // round as double and cast to int64_t
1105 // cast raised overflow error near max val of int64_t (~9.2e18, see unittest)
1106 int64_t input_casted_and_rounded =
1107 boost::numeric_cast<int64_t>( round(input) );
1110 return nice_unit_format( input_casted_and_rounded, format, base );
1111 } // eo nice_unit_format(double input)
1114 string escape(const string &s)
1117 string::size_type p;
1120 while ( (p=out.find_first_of("\"\\",p) ) !=out.npos)
1122 out.insert (p,"\\");
1127 while ( (p=out.find_first_of("\r",p) ) !=out.npos)
1129 out.replace (p,1,"\\r");
1134 while ( (p=out.find_first_of("\n",p) ) !=out.npos)
1136 out.replace (p,1,"\\n");
1143 } // eo scape(const std::string&)
1146 string descape(const string &s, int startpos, int &endpos)
1150 if (s.at(startpos) != '"')
1151 throw out_of_range("value not type escaped string");
1153 out=s.substr(startpos+1);
1154 string::size_type p=0;
1156 // search for the end of the string
1157 while ( (p=out.find("\"",p) ) !=out.npos)
1162 // the " might be escaped with a backslash
1163 while (e>=0 && out.at (e) =='\\')
1165 if (escaped == false)
1179 // we now have the end of the string
1180 out=out.substr(0,p);
1182 // tell calling prog about the endposition
1183 endpos=startpos+p+1;
1185 // descape all \ stuff inside the string now
1187 while ( (p=out.find_first_of("\\",p) ) !=out.npos)
1189 switch (out.at(p+1) )
1192 out.replace(p,2,"\r");
1195 out.replace(p,2,"\n");
1204 } // eo descape(const std::string&,int,int&)
1207 string escape_shellarg(const string &input)
1209 string output = "'";
1210 string::const_iterator it, it_end = input.end();
1211 for (it = input.begin(); it != it_end; ++it)