Branch data Line data Source code
1 : : // CubitString.cpp
2 : :
3 : :
4 : : #include "CubitString.hpp"
5 : : #include "CubitDefines.h"
6 : :
7 : : #ifdef _WIN32
8 : : #include <windows.h>
9 : : #define vsnprintf _vsnprintf
10 : : #endif
11 : :
12 : : #ifdef _MSC_VER
13 : : #pragma warning ( 4 : 4291 4244 4305 4018 )
14 : : #define va_copy(dest, src) (dest = src)
15 : : #endif
16 : :
17 : :
18 : : #include <iomanip>
19 : : #include <cstring>
20 : : #include <stdexcept>
21 : : #include <algorithm>
22 : : #include <stdarg.h>
23 : :
24 : : const size_t CubitString::npos = std::string::npos;
25 : :
26 : 349964 : CubitString::CubitString()
27 : : {
28 : 174982 : }
29 : :
30 : 1177606 : CubitString::CubitString(const CubitString& s)
31 : 1177606 : : rep(s.rep)
32 : : {
33 : 1177606 : }
34 : :
35 : 5009700 : CubitString::~CubitString()
36 : : {
37 : 2504850 : }
38 : :
39 : 2551654 : CubitString::CubitString(const char *s)
40 : : {
41 [ + - ]: 1275827 : if(s)
42 : : {
43 [ + - ]: 1275827 : rep = s;
44 : : }
45 : 1275827 : }
46 : :
47 : 0 : CubitString::CubitString(const std::string& s)
48 : 0 : : rep(s)
49 : : {
50 : 0 : }
51 : :
52 : 0 : CubitString::CubitString(int i, char c)
53 [ # # ]: 0 : : rep(i,c)
54 : : {
55 : 0 : }
56 : :
57 : 0 : CubitString CubitString::number(double f, unsigned int max_length, unsigned int sig_digits)
58 : : {
59 [ # # ][ # # ]: 0 : std::stringstream str;
60 [ # # ]: 0 : if(max_length)
61 : : {
62 [ # # ]: 0 : str.width(max_length);
63 : : }
64 [ # # ]: 0 : if(sig_digits)
65 : : {
66 [ # # ]: 0 : str.precision(sig_digits);
67 : : }
68 [ # # ]: 0 : str << f;
69 [ # # ][ # # ]: 0 : std::string ret = str.str();
70 [ # # ]: 0 : size_t i = ret.find_first_not_of(' ');
71 [ # # ]: 0 : if(i != std::string::npos)
72 [ # # ][ # # ]: 0 : ret = ret.substr(i);
[ # # ]
73 : :
74 : : // change precision to be short enough
75 [ # # ]: 0 : if (max_length)
76 : : {
77 [ # # ]: 0 : if(sig_digits == 0)
78 : 0 : sig_digits = max_length;
79 : :
80 [ # # ][ # # ]: 0 : while(ret.length() > max_length && sig_digits)
[ # # ][ # # ]
81 : : {
82 : 0 : sig_digits--;
83 [ # # ]: 0 : str.precision(sig_digits);
84 [ # # ][ # # ]: 0 : str.str(std::string());
[ # # ]
85 [ # # ]: 0 : str << f;
86 [ # # ][ # # ]: 0 : ret = str.str();
[ # # ]
87 : : }
88 : : }
89 [ # # ][ # # ]: 0 : return ret.c_str();
[ # # ]
90 : : }
91 : :
92 : 8242 : CubitString CubitString::format(const char* format, ...)
93 : : {
94 : : va_list args, args2;
95 : 8242 : va_start(args, format);
96 : : // copy because first vsnprintf modifies args
97 : 8242 : va_copy(args2, args);
98 : :
99 : : // how much room do we need for our string?
100 : 8242 : int num = vsnprintf(NULL, 0, format, args);
101 : :
102 : : // string plus null terminator
103 [ + - ]: 8242 : std::vector<char> str;
104 [ + - ]: 8242 : str.resize(num+1);
105 : :
106 : : // print string
107 [ + - ]: 8242 : num = vsnprintf(&str[0], num+1, format, args2);
108 : :
109 : : // remove extra null terminator
110 [ + - ]: 8242 : str.resize(num);
111 : :
112 : 8242 : va_end(args);
113 : 8242 : va_end(args2);
114 : :
115 [ + - ][ - + ]: 8242 : return str.empty() ? CubitString() : CubitString(&str[0]);
[ # # ][ + - ]
[ + - ][ + - ]
116 : : }
117 : :
118 : 114912 : CubitString& CubitString::operator=(const CubitString& s)
119 : : {
120 : 114912 : rep = s.rep;
121 : 114912 : return *this;
122 : : }
123 : :
124 : : #ifdef _WIN32
125 : : # define strcasecmp _stricmp
126 : : #endif
127 : :
128 : 0 : bool CubitString::compare(const CubitString& s, CaseSensitivity cs)
129 : : {
130 [ # # ]: 0 : if(cs == CaseSensitive)
131 : 0 : return this->rep == s.rep;
132 : :
133 : : // someday we might need to fix this to be unicode aware
134 [ # # ]: 0 : if(strcasecmp(this->rep.c_str(), s.rep.c_str()) == 0)
135 : 0 : return true;
136 : 0 : return false;
137 : : }
138 : :
139 : 24713 : char CubitString::get_at(size_t pos) const
140 : : {
141 : : // some legacy code wants to look for the null terminator
142 [ - + ]: 24713 : if(pos == rep.size())
143 : 0 : return 0;
144 : :
145 : 24713 : return rep.at(pos);
146 : : }
147 : :
148 : 0 : bool CubitString::is_empty() const
149 : : {
150 : 0 : return rep.empty();
151 : : }
152 : :
153 : 64419 : size_t CubitString::length() const
154 : : {
155 : 64419 : return rep.length();
156 : : }
157 : :
158 : 355738 : const char * CubitString::c_str() const
159 : : {
160 : 355738 : return rep.c_str();
161 : : }
162 : :
163 : 0 : const std::string& CubitString::str() const
164 : : {
165 : 0 : return rep;
166 : : }
167 : :
168 : 0 : void CubitString::clear()
169 : : {
170 : 0 : rep.clear();
171 : 0 : }
172 : :
173 : 0 : void CubitString::resize(size_t n)
174 : : {
175 : 0 : rep.resize(n);
176 : 0 : }
177 : :
178 : 0 : void CubitString::resize(size_t n, char c)
179 : : {
180 : 0 : rep.resize(n, c);
181 : 0 : }
182 : :
183 : :
184 : 9034 : CubitString operator+(const CubitString& s1, const CubitString& s2)
185 : : {
186 [ + - ][ + - ]: 9034 : return CubitString(s1) += s2;
187 : : }
188 : :
189 : 0 : CubitString operator+(const CubitString& s1, const char *c2)
190 : : {
191 [ # # ][ # # ]: 0 : return CubitString(s1) += c2;
[ # # ][ # # ]
192 : : }
193 : :
194 : 0 : CubitString operator+(const char *c1, const CubitString& s2)
195 : : {
196 [ # # ][ # # ]: 0 : return CubitString(c1) += s2;
197 : : }
198 : :
199 : 10039 : CubitString& CubitString::operator+=(const CubitString& s)
200 : : {
201 : 10039 : rep += s.rep;
202 : 10039 : return *this;
203 : : }
204 : :
205 : 0 : size_t CubitString::find(const CubitString& s, size_t pos) const
206 : : {
207 [ # # ][ # # ]: 0 : if(pos != 0 && pos >= rep.size())
[ # # ]
208 [ # # ][ # # ]: 0 : throw std::out_of_range("find index out of range");
209 : 0 : return rep.find(s.rep, pos);
210 : : }
211 : :
212 : 0 : size_t CubitString::find_first_of(const CubitString& s, size_t pos) const
213 : : {
214 : 0 : return rep.find_first_of(s.rep, pos);
215 : : }
216 : :
217 : 0 : size_t CubitString::find_first(char c, size_t pos) const
218 : : {
219 : 0 : return rep.find(c, pos);
220 : : }
221 : :
222 : 841 : size_t CubitString::find_last(char c, size_t pos) const
223 : : {
224 : 841 : return rep.find_last_of(c, pos);
225 : : }
226 : :
227 : :
228 : 1170 : CubitString CubitString::substr(size_t first, size_t count) const
229 : : {
230 [ - + ]: 1170 : if(first >= rep.size())
231 : 0 : return CubitString();
232 : :
233 [ + + ]: 1170 : if(count > rep.size() - first)
234 : 183 : count = rep.size() - first;
235 : :
236 [ + - ][ + - ]: 1170 : return rep.substr(first, count).c_str();
237 : : }
238 : :
239 : 0 : void CubitString::erase(size_t pos, size_t len)
240 : : {
241 : 0 : rep.erase(pos, len);
242 : 0 : }
243 : :
244 : 0 : void CubitString::replace(size_t pos, size_t len, const CubitString& str)
245 : : {
246 : 0 : rep.replace(pos, len, str.rep);
247 : 0 : }
248 : :
249 : 0 : void CubitString::replace(const CubitString& to_find, const CubitString& to_replace)
250 : : {
251 : 0 : size_t len = to_find.length();
252 : 0 : size_t len2 = to_replace.length();
253 [ # # ]: 0 : for(size_t idx = rep.find(to_find.c_str()); idx != npos; idx = rep.find(to_find.c_str(), idx))
254 : : {
255 : 0 : rep.replace(idx, len, to_replace.rep);
256 : 0 : idx += len2;
257 : : }
258 : 0 : }
259 : :
260 : 0 : bool CubitString::ends_with(const CubitString& str) const
261 : : {
262 [ # # ]: 0 : if(rep.size() >= str.rep.size())
263 : : {
264 : 0 : size_t offset = rep.size() - str.rep.size();
265 [ # # ][ # # ]: 0 : return std::equal(str.rep.begin(), str.rep.end(), rep.begin() + offset);
[ # # ][ # # ]
[ # # ]
266 : : }
267 : 0 : return false;
268 : : }
269 : :
270 : 0 : bool CubitString::starts_with(const CubitString& str) const
271 : : {
272 [ # # ]: 0 : if(rep.size() >= str.rep.size())
273 : : {
274 : 0 : return std::equal(str.rep.begin(), str.rep.end(), rep.begin());
275 : : }
276 : 0 : return false;
277 : : }
278 : :
279 : 1931 : void CubitString::put_at(size_t pos, char c)
280 : : {
281 : 1931 : rep.at(pos) = c;
282 : 1931 : }
283 : :
284 : 0 : void CubitString::to_lower()
285 : : {
286 [ # # ]: 0 : for(size_t i=0; i<rep.size(); i++)
287 : : {
288 : 0 : rep.at(i) = tolower(rep.at(i));
289 : : }
290 : 0 : }
291 : :
292 : 0 : void CubitString::to_upper()
293 : : {
294 [ # # ]: 0 : for(size_t i=0; i<rep.size(); i++)
295 : : {
296 : 0 : rep.at(i) = toupper(rep.at(i));
297 : : }
298 : 0 : }
299 : :
300 : 0 : void CubitString::to_lower(char *string)
301 : : {
302 : : // convert this string to lower case
303 : 0 : char *p = string;
304 [ # # ]: 0 : while (*p != '\0')
305 : : {
306 : 0 : *p = tolower (*p);
307 : 0 : p++;
308 : : }
309 : 0 : }
310 : :
311 : 0 : void CubitString::to_upper(char *string)
312 : : {
313 : : // convert this string to upper case
314 : 0 : char *p = string;
315 [ # # ]: 0 : while (*p != '\0')
316 : : {
317 : 0 : *p = toupper (*p);
318 : 0 : p++;
319 : : }
320 : 0 : }
321 : :
322 : 0 : void CubitString::trim()
323 : : {
324 : 0 : std::string::size_type start = rep.find_first_not_of(" \t\n\v\f\r");
325 : 0 : rep.erase(0, start);
326 : 0 : std::string::size_type end = rep.find_last_not_of(" \t\n\v\f\r");
327 : 0 : rep.erase(end+1, std::string::npos);
328 : 0 : }
329 : :
330 : 0 : void CubitString::simplify()
331 : : {
332 : 0 : trim();
333 [ # # ]: 0 : for(std::string::size_type i = rep.find_first_of(" \t\n\v\f\r"); i != std::string::npos;
334 : 0 : i = rep.find_first_of(" \t\n\v\f\r", i+1))
335 : : {
336 : 0 : std::string::size_type next_i = rep.find_first_not_of(" \t\n\v\f\r", i);
337 [ # # ]: 0 : if(next_i > i+1)
338 : : {
339 : 0 : rep.erase(i+1, next_i-i-1);
340 : 0 : rep.at(i) = ' ';
341 : : }
342 : : }
343 : 0 : }
344 : :
345 : 0 : void CubitString::tokenize( char delimiter, std::vector<CubitString> &strings ) const
346 : : {
347 [ # # ][ # # ]: 0 : std::stringstream ss(rep);
348 [ # # ][ # # ]: 0 : std::string s;
349 [ # # ][ # # ]: 0 : while(std::getline(ss, s, delimiter))
[ # # ]
350 [ # # ][ # # ]: 0 : strings.push_back(CubitString(s.c_str()));
[ # # ][ # # ]
[ # # ]
351 : 0 : }
352 : :
353 : 29374 : bool CubitString::operator==(const CubitString& s2) const
354 : : {
355 : 29374 : return rep == s2.rep;
356 : : }
357 : :
358 : 55088 : bool CubitString::operator!=(const CubitString& s2) const
359 : : {
360 : 55088 : return rep != s2.rep;
361 : : }
362 : :
363 : 0 : bool operator<=(const CubitString& s1, const CubitString& s2)
364 : : {
365 : 0 : return s1.rep <= s2.rep;
366 : : }
367 : :
368 : 40 : bool operator>=(const CubitString& s1, const CubitString& s2)
369 : : {
370 : 40 : return s1.rep >= s2.rep;
371 : : }
372 : :
373 : 418767 : bool operator<( const CubitString& s1, const CubitString& s2 )
374 : : {
375 : 418767 : return s1.rep < s2.rep;
376 : : }
377 : :
378 : 0 : bool operator>( const CubitString& s1, const CubitString& s2 )
379 : : {
380 : 0 : return s1.rep > s2.rep;
381 : : }
382 : :
383 : : #if defined(_WIN32)
384 : :
385 : : std::wstring CubitString::toUtf16(const char* str)
386 : : {
387 : : // there are other methods (e.g. C++11), but since its Windows specific to support Windows APIs, just use their API.
388 : : std::wstring ret;
389 : : int sz = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
390 : : if(sz)
391 : : {
392 : : std::vector<wchar_t> result(sz);
393 : : MultiByteToWideChar(CP_UTF8, 0, str, -1, &result[0], sz);
394 : : ret = &result[0];
395 : : }
396 : : return ret;
397 : : }
398 : :
399 : : std::wstring CubitString::toUtf16(const CubitString& str)
400 : : {
401 : : return toUtf16(str.c_str());
402 : : }
403 : :
404 : : CubitString CubitString::toUtf8(const wchar_t* str)
405 : : {
406 : : CubitString ret;
407 : : int sz = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
408 : : if(sz)
409 : : {
410 : : std::vector<char> result(sz);
411 : : WideCharToMultiByte(CP_UTF8, 0, str, -1, &result[0], sz, NULL, NULL);
412 : : ret = &result[0];
413 : : }
414 : : return ret;
415 : : }
416 : :
417 : : #endif
418 : :
419 : : #if defined(_MSC_VER)
420 : :
421 : : std::wstring CubitString::toNative(const char* str)
422 : : {
423 : : return toUtf16(str);
424 : : }
425 : :
426 : : std::wstring CubitString::toNative(const CubitString& str)
427 : : {
428 : : return toUtf16(str);
429 : : }
430 : :
431 : : #else
432 : :
433 : 0 : CubitString CubitString::toNative(const char* str)
434 : : {
435 : 0 : return str;
436 : : }
437 : :
438 : 0 : CubitString CubitString::toNative(const CubitString& str)
439 : : {
440 : 0 : return str;
441 : : }
442 : :
443 : : #endif
444 : :
445 : 0 : std::wstring CubitString::toWide(const CubitString& str)
446 : : {
447 : : #ifdef _WIN32
448 : : return toUtf16(str);
449 : : #else
450 : 0 : std::wstring wstr;
451 [ # # ]: 0 : size_t len = mbstowcs(NULL, str.c_str(), 0) + 1;
452 [ # # ]: 0 : if(len > 0)
453 : : {
454 [ # # ]: 0 : std::vector<wchar_t> wchar(len);
455 [ # # ][ # # ]: 0 : mbstowcs(&wchar[0], str.c_str(), len);
456 [ # # ][ # # ]: 0 : wstr = &wchar[0];
[ # # ]
457 : : }
458 : 0 : return wstr;
459 : : #endif
460 : : }
461 : :
462 : 0 : CubitString CubitString::toNarrow(const std::wstring& wstr)
463 : : {
464 : : #ifdef _WIN32
465 : : return toUtf8(wstr.c_str()).c_str();
466 : : #else
467 : 0 : CubitString str;
468 [ # # ]: 0 : size_t len = wcstombs(NULL, wstr.c_str(), 0) + 1;
469 [ # # ]: 0 : if(len > 0)
470 : : {
471 [ # # ]: 0 : std::vector<char> chars(len);
472 [ # # ][ # # ]: 0 : wcstombs(&chars[0], wstr.c_str(), len);
473 [ # # ][ # # ]: 0 : str = &chars[0];
[ # # ][ # # ]
[ # # ]
474 : : }
475 : 0 : return str;
476 : : #endif
477 : : }
478 : :
479 : :
480 : :
481 : : #ifdef TEST_STRING
482 : :
483 : : void main() {
484 : : CubitString a = "Test ";
485 : : CubitString b = "String Class";
486 : : CubitString blank(' ');
487 : :
488 : : CubitString c = a + b;
489 : : c+= b;
490 : : CubitString e = c;
491 : : CubitString f = c;
492 : : CubitString g = c;
493 : : g.put_at(1, 'Z');
494 : : cout << "G = " << g << endl;
495 : : cout << "C = " << c << endl;
496 : :
497 : : c.put_at(1, 'X');
498 : : CubitString d = b;
499 : : d.put_at(1, 'Y');
500 : : }
501 : : #endif
|