3 This file is part of libmspstrings
4 Copyright © 2006-2007 Mikko Rasa
5 Distributed under the LGPL
9 #include <msp/core/error.h>
16 template<bool long_sep, bool allow_empty>
17 vector<string> do_split(const string &str, const string &sep, int max_split)
19 vector<string> result;
22 while(start<str.size())
24 unsigned end=long_sep ? str.find(sep, start) : str.find_first_of(sep, start);
25 if(end!=start || allow_empty)
27 if(max_split>=0 && result.size()==static_cast<unsigned>(max_split))
29 result.push_back(str.substr(start));
33 result.push_back(str.substr(start, end-start));
39 start=end+(long_sep ? sep.size() : 1);
41 if(allow_empty && start==str.size())
42 result.push_back(string());
52 int strcasecmp(const string &s1, const string &s2)
54 string::const_iterator i1=s1.begin();
55 string::const_iterator i2=s2.begin();
56 for(; (i1!=s1.end() && i2!=s2.end()); ++i1, ++i2)
58 const char c1=::tolower(*i1);
59 const char c2=::tolower(*i2);
60 if(c1!=c2) return c1-c2;
62 if(i1!=s1.end()) return *i1;
63 if(i2!=s2.end()) return -*i2;
67 string tolower(const string &str)
70 transform(result.begin(), result.end(), result.begin(), ::tolower);
74 string toupper(const string &str)
77 transform(result.begin(), result.end(), result.begin(), ::toupper);
81 vector<string> split(const string &str, const string &sep, int max_split)
83 return do_split<false, false>(str, sep, max_split);
86 vector<string> split(const string &str, char sep, int max_split)
88 return split(str, string(1, sep), max_split);
91 vector<string> split_long(const string &str, const string &sep, int max_split)
93 return do_split<true, false>(str, sep, max_split);
96 vector<string> split_fields(const string &str, const string &sep, int max_split)
98 return do_split<true, true>(str, sep, max_split);
101 vector<string> split_fields(const string &str, char sep, int max_split)
103 return split_fields(str, string(1, sep), max_split);
107 Splits a string to parts.
109 @param str String to be split
110 @param sep A set of separator characters
111 @param allow_empty Whether or not to produce empty parts for sequences of
112 more than one separator character
114 vector<string> split(const string &str, const string &sep, bool allow_empty)
116 vector<string> result;
120 start=str.find_first_not_of(sep);
122 while(start<str.size())
124 unsigned end=str.find_first_of(sep, start);
125 result.push_back(str.substr(start, end-start));
127 if(end==string::npos)
133 if(start==str.size())
134 result.push_back(string());
137 start=str.find_first_not_of(sep, end);
143 vector<string> split(const string &str, char sep, bool allow_empty)
145 return split(str, string(1, sep), allow_empty);
148 string strip(const string &s)
151 if(!result.erase(0, result.find_first_not_of(" \t\r\n")).empty())
152 result.erase(result.find_last_not_of(" \t\r\n")+1);
156 string c_unescape(const std::string &str)
159 unsigned numeric_type=0;
160 unsigned numeric_pos=0;
161 unsigned numeric_value=0;
163 for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
168 if(*i>='0' && *i<='9')
170 else if(*i>='a' && *i<='f')
172 else if(*i>='A' && *i<='F')
175 throw InvalidParameterValue("Invalid hexadecimal digit");
177 numeric_value=(numeric_value<<4 | digit);
181 result+=numeric_value;
185 else if(numeric_type==2)
188 if(*i>='0' && *i<='7')
191 throw InvalidParameterValue("Invalid octal digit");
193 if(numeric_pos==0 && digit>3)
194 throw InvalidParameterValue("Octal escape sequence must start with [0-3]");
196 numeric_value=(numeric_value<<3 | digit);
200 result+=numeric_value;
206 if(*i=='x' || (*i>='0' && *i<='7'))
208 numeric_type=(*i=='x' ? 1 : 2);
233 throw InvalidParameterValue("Invalid escape sequence");
244 throw InvalidParameterValue("Stray backslash at end of string");
249 string c_escape(const string &str, bool escape_8bit)
253 for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
275 else if(*i<' ' || (escape_8bit && (*i&0x80)))
277 char buf[4]={'\\', (*i>>6)&7, (*i>>3)&7, *i&7};
278 result.append(buf, 4);