]> git.mxchange.org Git - simgear.git/blob - simgear/misc/strutils.cxx
Add strutils::starts_with and strutils::ends_with
[simgear.git] / simgear / misc / strutils.cxx
1 // String utilities.
2 //
3 // Written by Bernie Bright, started 1998
4 //
5 // Copyright (C) 1998  Bernie Bright - bbright@bigpond.net.au
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23 #include <ctype.h>
24 #include <cstring>
25
26 #include "strutils.hxx"
27
28 using std::string;
29 using std::vector;
30
31 namespace simgear {
32     namespace strutils {
33
34         /**
35          * 
36          */
37         static vector<string>
38         split_whitespace( const string& str, int maxsplit )
39         {
40             vector<string> result;
41             string::size_type len = str.length();
42             string::size_type i = 0;
43             string::size_type j;
44             int countsplit = 0;
45
46             while (i < len)
47             {
48                 while (i < len && isspace((unsigned char)str[i]))
49                 {
50                     ++i;
51                 }
52
53                 j = i;
54
55                 while (i < len && !isspace((unsigned char)str[i]))
56                 {
57                     ++i;
58                 }
59
60                 if (j < i)
61                 {
62                     result.push_back( str.substr(j, i-j) );
63                     ++countsplit;
64                     while (i < len && isspace((unsigned char)str[i]))
65                     {
66                         ++i;
67                     }
68
69                     if (maxsplit && (countsplit >= maxsplit) && i < len)
70                     {
71                         result.push_back( str.substr( i, len-i ) );
72                         i = len;
73                     }
74                 }
75             }
76
77             return result;
78         }
79
80         /**
81          * 
82          */
83         vector<string>
84         split( const string& str, const char* sep, int maxsplit )
85         {
86             if (sep == 0)
87                 return split_whitespace( str, maxsplit );
88
89             vector<string> result;
90             int n = std::strlen( sep );
91             if (n == 0)
92             {
93                 // Error: empty separator string
94                 return result;
95             }
96             const char* s = str.c_str();
97             string::size_type len = str.length();
98             string::size_type i = 0;
99             string::size_type j = 0;
100             int splitcount = 0;
101
102             while (i+n <= len)
103             {
104                 if (s[i] == sep[0] && (n == 1 || std::memcmp(s+i, sep, n) == 0))
105                 {
106                     result.push_back( str.substr(j,i-j) );
107                     i = j = i + n;
108                     ++splitcount;
109                     if (maxsplit && (splitcount >= maxsplit))
110                         break;
111                 }
112                 else
113                 {
114                     ++i;
115                 }
116             }
117
118             result.push_back( str.substr(j,len-j) );
119             return result;
120         }
121
122         /**
123          * The lstrip(), rstrip() and strip() functions are implemented
124          * in do_strip() which uses an additional parameter to indicate what
125          * type of strip should occur.
126          */
127         const int LEFTSTRIP = 0;
128         const int RIGHTSTRIP = 1;
129         const int BOTHSTRIP = 2;
130
131         static string
132         do_strip( const string& s, int striptype )
133         {
134             string::size_type len = s.length();
135             if( len == 0 ) // empty string is trivial
136                 return s;
137             string::size_type i = 0;
138             if (striptype != RIGHTSTRIP)
139             {
140                 while (i < len && isspace(s[i]))
141                 {
142                     ++i;
143                 }
144             }
145
146             string::size_type j = len;
147             if (striptype != LEFTSTRIP)
148             {
149                 do
150                 {
151                     --j;
152                 }
153                 while (j >= 1 && isspace(s[j]));
154                 ++j;
155             }
156
157             if (i == 0 && j == len)
158             {
159                 return s;
160             }
161             else
162             {
163                 return s.substr( i, j - i );
164             }
165         }
166
167         string
168         lstrip( const string& s )
169         {
170             return do_strip( s, LEFTSTRIP );
171         }
172
173         string
174         rstrip( const string& s )
175         {
176             return do_strip( s, RIGHTSTRIP );
177         }
178
179         string
180         strip( const string& s )
181         {
182             return do_strip( s, BOTHSTRIP );
183         }
184
185         string 
186         rpad( const string & s, string::size_type length, char c )
187         {
188             string::size_type l = s.length();
189             if( l >= length ) return s;
190             string reply = s;
191             return reply.append( length-l, c );
192         }
193
194         string 
195         lpad( const string & s, size_t length, char c )
196         {
197             string::size_type l = s.length();
198             if( l >= length ) return s;
199             string reply = s;
200             return reply.insert( 0, length-l, c );
201         }
202
203         bool
204         starts_with( const string & s, const string & substr )
205         {       
206                 return s.find( substr ) == 0;
207         }
208
209         bool
210         ends_with( const string & s, const string & substr )
211         {       
212                 size_t n = s.rfind( substr );
213                 return (n != string::npos) && (n == s.length() - substr.length());
214         }
215
216     } // end namespace strutils
217 } // end namespace simgear