String.cc (10447:a465576671d4) String.cc (10448:bc1a3b7ab5ef)
1/* Copyright (c) 2012 Massachusetts Institute of Technology
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 * THE SOFTWARE.
20 */
21
1#include "String.h"
2
3#include <cstdarg>
4#include <cstdio>
5#include <iostream>
6#include <ios>
7
8namespace LibUtil
9{
10 const unsigned int String::msBufferSize = 4096;
11
12 String String::format(const String& format_, ...)
13 {
14 char buffer[msBufferSize];
15
16 va_list args;
17 va_start(args, format_);
18 vsnprintf(buffer, msBufferSize, format_.c_str(), args);
19 va_end(args);
20
21 return (String)(buffer);
22 }
23
24 String String::format(const String& format_, va_list args_)
25 {
26 char buffer[msBufferSize];
27
28 vsnprintf(buffer, msBufferSize, format_.c_str(), args_);
29
30 return (String)(buffer);
31 }
32
33 String::String()
34 {}
35
36 String::String(const string& str_)
37 : string(str_)
38 {}
39
40 String::String(const char* str_, size_t n_)
41 : string(str_, n_)
42 {}
43
44 String::String(const char* str_)
45 : string(str_)
46 {}
47
48 String::String(size_t n_, char c_)
49 : string(n_, c_)
50 {}
51
52 String::String(int value_)
53 : string(toString<int>(value_))
54 {}
55
56 String::String(unsigned int value_)
57 : string(toString<unsigned int>(value_))
58 {}
59
60 String::String(long value_)
61 : string(toString<long>(value_))
62 {}
63
64 String::String(unsigned long value_)
65 : string(toString<unsigned long>(value_))
66 {}
67
68 String::String(float value_)
69 : string(toString<float>(value_))
70 {}
71
72 String::String(double value_)
73 : string(toString<double>(value_))
74 {}
75
76 String::String(bool value_)
77 : string(toString<bool>(value_))
78 {}
79
80 String::~String()
81 {}
82
83 String& String::trim()
84 {
85 // Remove leading and trailing whitespace
86 static const char whitespace[] = " \n\t\v\r\f";
87 erase(0, find_first_not_of(whitespace));
88 erase(find_last_not_of(whitespace) + 1U);
89 return (*this);
90 }
91
92 String& String::substitute(const String& str1_, const String& str2_)
93 {
94 size_t str1Size = str1_.size();
95 size_t str2Size = str2_.size();
96
97 size_t pos;
98 pos = find(str1_);
99 while(pos != string::npos)
100 {
101 replace(pos, str1Size, str2_);
102 pos += str2Size;
103 pos = find(str1_, pos);
104 }
105 return (*this);
106 }
107
108 vector<String> String::split(const char* delimiters_) const
109 {
110 vector<String> result;
111
112 if(size() == 0)
113 {
114 return result;
115 }
116
117 size_t currPos, nextPos;
118 currPos = 0;
119 nextPos = find_first_of(delimiters_);
120 while(1)
121 {
122 if(nextPos == string::npos)
123 {
124 if(currPos != size())
125 {
126 result.push_back(substr(currPos));
127 }
128 break;
129 }
130
131 if(nextPos != currPos)
132 {
133 result.push_back(substr(currPos, nextPos - currPos));
134 }
135 currPos = nextPos + 1;
136 nextPos = find_first_of(delimiters_, currPos);
137 }
138
139 return result;
140 }
141
142 vector<String> String::split(const String* delimiters_, unsigned int num_delimiters_) const
143 {
144 vector<String> result;
145
146 if(size() == 0)
147 {
148 return result;
149 }
150
151 if(num_delimiters_ == 1)
152 {
153 size_t currPos, nextPos;
154 currPos = 0;
155 nextPos = find(delimiters_[0]);
156 while(1)
157 {
158 if(nextPos == String::npos)
159 {
160 result.push_back(substr(currPos));
161 break;
162 }
163
164 if(nextPos != currPos)
165 {
166 result.push_back(substr(currPos, nextPos - currPos));
167 }
168 currPos = nextPos + delimiters_[0].size();
169 nextPos = find(delimiters_[0], currPos);
170 }
171 }
172 else
173 {
174 // Currently the length of the delimiters are not checked
175 unsigned int delimiterLength = 0;
176 size_t currPos, nextPos;
177 currPos = 0;
178 nextPos = size();
179 for(unsigned int i = 0; i < num_delimiters_; ++i)
180 {
181 size_t tempPos = find(delimiters_[i], currPos);
182 if((tempPos != String::npos) && (tempPos < nextPos))
183 {
184 nextPos = tempPos;
185 delimiterLength = delimiters_[i].size();
186 }
187 }
188 while(1)
189 {
190 if((nextPos == String::npos) || (nextPos == size()))
191 {
192 result.push_back(substr(currPos));
193 break;
194 }
195
196 if(nextPos != currPos)
197 {
198 result.push_back(substr(currPos, nextPos - currPos));
199 }
200 currPos = nextPos + delimiterLength;
201 nextPos = size();
202 delimiterLength = 0;
203 for(unsigned int i = 0; i < num_delimiters_; ++i)
204 {
205 size_t tempPos = find(delimiters_[i], currPos);
206 if((tempPos != String::npos) && (tempPos < nextPos))
207 {
208 nextPos = tempPos;
209 delimiterLength = delimiters_[i].size();
210 }
211 }
212 }
213 }
214 return result;
215 }
216
217 vector<String> String::splitByString(const String& delimiter_) const
218 {
219 return split(&delimiter_, 1);
220 }
221
222 bool String::contain(const String& str_) const
223 {
224 return (find(str_) != String::npos);
225 }
226
227 const char* String::toCString() const
228 {
229 return this->c_str();
230 }
231
232 int String::toInt() const
233 {
234 return fromString<int>(*this);
235 }
236
237 unsigned int String::toUInt() const
238 {
239 return fromString<unsigned int>(*this);
240 }
241
242 long String::toLong() const
243 {
244 return fromString<long>(*this);
245 }
246
247 unsigned long String::toULong() const
248 {
249 return fromString<unsigned long>(*this);
250 }
251
252 float String::toFloat() const
253 {
254 return fromString<float>(*this);
255 }
256
257 double String::toDouble() const
258 {
259 return fromString<double>(*this);
260 }
261
262 bool String::toBool() const
263 {
264 return fromString<bool>(*this);
265 }
266
267 String::operator const char*() const
268 {
269 return this->c_str();
270 }
271
272 String::operator int() const
273 {
274 return fromString<int>(*this);
275 }
276
277 String::operator unsigned int() const
278 {
279 return fromString<unsigned int>(*this);
280 }
281
282 String::operator long() const
283 {
284 return fromString<long>(*this);
285 }
286
287 String::operator unsigned long() const
288 {
289 return fromString<unsigned long>(*this);
290 }
291
292 String::operator float() const
293 {
294 return fromString<float>(*this);
295 }
296
297 String::operator double() const
298 {
299 return fromString<double>(*this);
300 }
301
302 String::operator bool() const
303 {
304 return fromString<bool>(*this);
305 }
306
307 String& String::operator=(char c_)
308 {
309 this->assign(1, c_);
310 return *this;
311 }
312
313 std::istream& safeGetline(std::istream& is_, String& str_)
314 {
315 str_.clear();
316
317 // The characters in the stream are read one-by-one using a std::streambuf.
318 // That is faster than reading them one-by-one using the std::istream.
319 // Code that uses streambuf this way must be guarded by a sentry object.
320 // The sentry object performs various tasks,
321 // such as thread synchronization and updating the stream state.
322
323 std::istream::sentry se(is_, true);
324 std::streambuf* sb = is_.rdbuf();
325
326 while(1)
327 {
328 int c = sb->sbumpc();
329 switch(c)
330 {
331 case '\r':
332 c = sb->sgetc();
333 if(c == '\n')
334 sb->sbumpc();
335 return is_;
336 case '\n':
337 return is_;
338 case EOF:
339 is_.setstate(std::ios_base::failbit|std::ios_base::eofbit);
340 return is_;
341 default:
342 str_ += String(1, (char)c);
343 }
344 }
345 }
346} // namespace LibUtil
347
22#include "String.h"
23
24#include <cstdarg>
25#include <cstdio>
26#include <iostream>
27#include <ios>
28
29namespace LibUtil
30{
31 const unsigned int String::msBufferSize = 4096;
32
33 String String::format(const String& format_, ...)
34 {
35 char buffer[msBufferSize];
36
37 va_list args;
38 va_start(args, format_);
39 vsnprintf(buffer, msBufferSize, format_.c_str(), args);
40 va_end(args);
41
42 return (String)(buffer);
43 }
44
45 String String::format(const String& format_, va_list args_)
46 {
47 char buffer[msBufferSize];
48
49 vsnprintf(buffer, msBufferSize, format_.c_str(), args_);
50
51 return (String)(buffer);
52 }
53
54 String::String()
55 {}
56
57 String::String(const string& str_)
58 : string(str_)
59 {}
60
61 String::String(const char* str_, size_t n_)
62 : string(str_, n_)
63 {}
64
65 String::String(const char* str_)
66 : string(str_)
67 {}
68
69 String::String(size_t n_, char c_)
70 : string(n_, c_)
71 {}
72
73 String::String(int value_)
74 : string(toString<int>(value_))
75 {}
76
77 String::String(unsigned int value_)
78 : string(toString<unsigned int>(value_))
79 {}
80
81 String::String(long value_)
82 : string(toString<long>(value_))
83 {}
84
85 String::String(unsigned long value_)
86 : string(toString<unsigned long>(value_))
87 {}
88
89 String::String(float value_)
90 : string(toString<float>(value_))
91 {}
92
93 String::String(double value_)
94 : string(toString<double>(value_))
95 {}
96
97 String::String(bool value_)
98 : string(toString<bool>(value_))
99 {}
100
101 String::~String()
102 {}
103
104 String& String::trim()
105 {
106 // Remove leading and trailing whitespace
107 static const char whitespace[] = " \n\t\v\r\f";
108 erase(0, find_first_not_of(whitespace));
109 erase(find_last_not_of(whitespace) + 1U);
110 return (*this);
111 }
112
113 String& String::substitute(const String& str1_, const String& str2_)
114 {
115 size_t str1Size = str1_.size();
116 size_t str2Size = str2_.size();
117
118 size_t pos;
119 pos = find(str1_);
120 while(pos != string::npos)
121 {
122 replace(pos, str1Size, str2_);
123 pos += str2Size;
124 pos = find(str1_, pos);
125 }
126 return (*this);
127 }
128
129 vector<String> String::split(const char* delimiters_) const
130 {
131 vector<String> result;
132
133 if(size() == 0)
134 {
135 return result;
136 }
137
138 size_t currPos, nextPos;
139 currPos = 0;
140 nextPos = find_first_of(delimiters_);
141 while(1)
142 {
143 if(nextPos == string::npos)
144 {
145 if(currPos != size())
146 {
147 result.push_back(substr(currPos));
148 }
149 break;
150 }
151
152 if(nextPos != currPos)
153 {
154 result.push_back(substr(currPos, nextPos - currPos));
155 }
156 currPos = nextPos + 1;
157 nextPos = find_first_of(delimiters_, currPos);
158 }
159
160 return result;
161 }
162
163 vector<String> String::split(const String* delimiters_, unsigned int num_delimiters_) const
164 {
165 vector<String> result;
166
167 if(size() == 0)
168 {
169 return result;
170 }
171
172 if(num_delimiters_ == 1)
173 {
174 size_t currPos, nextPos;
175 currPos = 0;
176 nextPos = find(delimiters_[0]);
177 while(1)
178 {
179 if(nextPos == String::npos)
180 {
181 result.push_back(substr(currPos));
182 break;
183 }
184
185 if(nextPos != currPos)
186 {
187 result.push_back(substr(currPos, nextPos - currPos));
188 }
189 currPos = nextPos + delimiters_[0].size();
190 nextPos = find(delimiters_[0], currPos);
191 }
192 }
193 else
194 {
195 // Currently the length of the delimiters are not checked
196 unsigned int delimiterLength = 0;
197 size_t currPos, nextPos;
198 currPos = 0;
199 nextPos = size();
200 for(unsigned int i = 0; i < num_delimiters_; ++i)
201 {
202 size_t tempPos = find(delimiters_[i], currPos);
203 if((tempPos != String::npos) && (tempPos < nextPos))
204 {
205 nextPos = tempPos;
206 delimiterLength = delimiters_[i].size();
207 }
208 }
209 while(1)
210 {
211 if((nextPos == String::npos) || (nextPos == size()))
212 {
213 result.push_back(substr(currPos));
214 break;
215 }
216
217 if(nextPos != currPos)
218 {
219 result.push_back(substr(currPos, nextPos - currPos));
220 }
221 currPos = nextPos + delimiterLength;
222 nextPos = size();
223 delimiterLength = 0;
224 for(unsigned int i = 0; i < num_delimiters_; ++i)
225 {
226 size_t tempPos = find(delimiters_[i], currPos);
227 if((tempPos != String::npos) && (tempPos < nextPos))
228 {
229 nextPos = tempPos;
230 delimiterLength = delimiters_[i].size();
231 }
232 }
233 }
234 }
235 return result;
236 }
237
238 vector<String> String::splitByString(const String& delimiter_) const
239 {
240 return split(&delimiter_, 1);
241 }
242
243 bool String::contain(const String& str_) const
244 {
245 return (find(str_) != String::npos);
246 }
247
248 const char* String::toCString() const
249 {
250 return this->c_str();
251 }
252
253 int String::toInt() const
254 {
255 return fromString<int>(*this);
256 }
257
258 unsigned int String::toUInt() const
259 {
260 return fromString<unsigned int>(*this);
261 }
262
263 long String::toLong() const
264 {
265 return fromString<long>(*this);
266 }
267
268 unsigned long String::toULong() const
269 {
270 return fromString<unsigned long>(*this);
271 }
272
273 float String::toFloat() const
274 {
275 return fromString<float>(*this);
276 }
277
278 double String::toDouble() const
279 {
280 return fromString<double>(*this);
281 }
282
283 bool String::toBool() const
284 {
285 return fromString<bool>(*this);
286 }
287
288 String::operator const char*() const
289 {
290 return this->c_str();
291 }
292
293 String::operator int() const
294 {
295 return fromString<int>(*this);
296 }
297
298 String::operator unsigned int() const
299 {
300 return fromString<unsigned int>(*this);
301 }
302
303 String::operator long() const
304 {
305 return fromString<long>(*this);
306 }
307
308 String::operator unsigned long() const
309 {
310 return fromString<unsigned long>(*this);
311 }
312
313 String::operator float() const
314 {
315 return fromString<float>(*this);
316 }
317
318 String::operator double() const
319 {
320 return fromString<double>(*this);
321 }
322
323 String::operator bool() const
324 {
325 return fromString<bool>(*this);
326 }
327
328 String& String::operator=(char c_)
329 {
330 this->assign(1, c_);
331 return *this;
332 }
333
334 std::istream& safeGetline(std::istream& is_, String& str_)
335 {
336 str_.clear();
337
338 // The characters in the stream are read one-by-one using a std::streambuf.
339 // That is faster than reading them one-by-one using the std::istream.
340 // Code that uses streambuf this way must be guarded by a sentry object.
341 // The sentry object performs various tasks,
342 // such as thread synchronization and updating the stream state.
343
344 std::istream::sentry se(is_, true);
345 std::streambuf* sb = is_.rdbuf();
346
347 while(1)
348 {
349 int c = sb->sbumpc();
350 switch(c)
351 {
352 case '\r':
353 c = sb->sgetc();
354 if(c == '\n')
355 sb->sbumpc();
356 return is_;
357 case '\n':
358 return is_;
359 case EOF:
360 is_.setstate(std::ios_base::failbit|std::ios_base::eofbit);
361 return is_;
362 default:
363 str_ += String(1, (char)c);
364 }
365 }
366 }
367} // namespace LibUtil
368