3 // Written by Bernie Bright, started 1998
5 // Copyright (C) 1998 Bernie Bright - bbright@bigpond.net.au
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Library General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include "strutils.hxx"
31 using std::stringstream;
40 split_whitespace( const string& str, int maxsplit )
42 vector<string> result;
43 string::size_type len = str.length();
44 string::size_type i = 0;
50 while (i < len && isspace((unsigned char)str[i]))
57 while (i < len && !isspace((unsigned char)str[i]))
64 result.push_back( str.substr(j, i-j) );
66 while (i < len && isspace((unsigned char)str[i]))
71 if (maxsplit && (countsplit >= maxsplit) && i < len)
73 result.push_back( str.substr( i, len-i ) );
86 split( const string& str, const char* sep, int maxsplit )
89 return split_whitespace( str, maxsplit );
91 vector<string> result;
92 int n = std::strlen( sep );
95 // Error: empty separator string
98 const char* s = str.c_str();
99 string::size_type len = str.length();
100 string::size_type i = 0;
101 string::size_type j = 0;
106 if (s[i] == sep[0] && (n == 1 || std::memcmp(s+i, sep, n) == 0))
108 result.push_back( str.substr(j,i-j) );
111 if (maxsplit && (splitcount >= maxsplit))
120 result.push_back( str.substr(j,len-j) );
125 * The lstrip(), rstrip() and strip() functions are implemented
126 * in do_strip() which uses an additional parameter to indicate what
127 * type of strip should occur.
129 const int LEFTSTRIP = 0;
130 const int RIGHTSTRIP = 1;
131 const int BOTHSTRIP = 2;
134 do_strip( const string& s, int striptype )
136 string::size_type len = s.length();
137 if( len == 0 ) // empty string is trivial
139 string::size_type i = 0;
140 if (striptype != RIGHTSTRIP)
142 while (i < len && isspace(s[i]))
148 string::size_type j = len;
149 if (striptype != LEFTSTRIP)
155 while (j >= 1 && isspace(s[j]));
159 if (i == 0 && j == len)
165 return s.substr( i, j - i );
170 lstrip( const string& s )
172 return do_strip( s, LEFTSTRIP );
176 rstrip( const string& s )
178 return do_strip( s, RIGHTSTRIP );
182 strip( const string& s )
184 return do_strip( s, BOTHSTRIP );
188 rpad( const string & s, string::size_type length, char c )
190 string::size_type l = s.length();
191 if( l >= length ) return s;
193 return reply.append( length-l, c );
197 lpad( const string & s, size_t length, char c )
199 string::size_type l = s.length();
200 if( l >= length ) return s;
202 return reply.insert( 0, length-l, c );
206 starts_with( const string & s, const string & substr )
208 return s.find( substr ) == 0;
212 ends_with( const string & s, const string & substr )
214 size_t n = s.rfind( substr );
215 return (n != string::npos) && (n == s.length() - substr.length());
218 string simplify(const string& s)
220 string result; // reserve size of 's'?
221 string::const_iterator it = s.begin(),
224 // advance to first non-space char - simplifes logic in main loop,
225 // since we can always prepend a single space when we see a
226 // space -> non-space transition
227 for (; (it != end) && isspace(*it); ++it) { /* nothing */ }
229 bool lastWasSpace = false;
230 for (; it != end; ++it) {
238 result.push_back(' ');
241 lastWasSpace = false;
248 int to_int(const std::string& s, int base)
252 case 8: ss >> std::oct; break;
253 case 16: ss >> std::hex; break;
262 int compare_versions(const string& v1, const string& v2)
264 vector<string> v1parts(split(v1, "."));
265 vector<string> v2parts(split(v2, "."));
267 int lastPart = std::min(v1parts.size(), v2parts.size());
268 for (int part=0; part < lastPart; ++part) {
269 int part1 = to_int(v1parts[part]);
270 int part2 = to_int(v2parts[part]);
272 if (part1 != part2) {
273 return part1 - part2;
275 } // of parts iteration
277 // reached end - longer wins
278 return v1parts.size() - v2parts.size();
281 string join(const string_list& l, const string& joinWith)
284 unsigned int count = l.size();
285 for (unsigned int i=0; i < count; ++i) {
287 if (i < (count - 1)) {
295 } // end namespace strutils
297 } // end namespace simgear