root / trunk / Windows / libs / poco / include / Poco / String.h @ 3

View | Annotate | Download (14.3 KB)

1
//
2
// String.h
3
//
4
// $Id: //poco/1.3/Foundation/include/Poco/String.h#4 $
5
//
6
// Library: Foundation
7
// Package: Core
8
// Module:  String
9
//
10
// String utility functions.
11
//
12
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
13
// and Contributors.
14
//
15
// Permission is hereby granted, free of charge, to any person or organization
16
// obtaining a copy of the software and accompanying documentation covered by
17
// this license (the "Software") to use, reproduce, display, distribute,
18
// execute, and transmit the Software, and to prepare derivative works of the
19
// Software, and to permit third-parties to whom the Software is furnished to
20
// do so, all subject to the following:
21
// 
22
// The copyright notices in the Software and this entire statement, including
23
// the above license grant, this restriction and the following disclaimer,
24
// must be included in all copies of the Software, in whole or in part, and
25
// all derivative works of the Software, unless such copies or derivative
26
// works are solely in the form of machine-executable object code generated by
27
// a source language processor.
28
// 
29
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
32
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
33
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
34
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
35
// DEALINGS IN THE SOFTWARE.
36
//
37
38
39
#ifndef Foundation_String_INCLUDED
40
#define Foundation_String_INCLUDED
41
42
43
#include "Poco/Foundation.h"
44
#include <cstring>
45
#include <cctype>
46
47
48
namespace Poco {
49
50
51
template <class S>
52
S trimLeft(const S& str)
53
        /// Returns a copy of str with all leading
54
        /// whitespace removed.
55
{
56
        typename S::const_iterator it  = str.begin();
57
        typename S::const_iterator end = str.end();
58
        
59
        while (it != end && std::isspace(*it)) ++it;
60
        return S(it, end);
61
}
62
63
64
template <class S>
65
S& trimLeftInPlace(S& str)
66
        /// Removes all leading whitespace in str.
67
{
68
        typename S::iterator it  = str.begin();
69
        typename S::iterator end = str.end();
70
        
71
        while (it != end && std::isspace(*it)) ++it;
72
        str.erase(str.begin(), it);
73
        return str;
74
}
75
76
77
template <class S>
78
S trimRight(const S& str)
79
        /// Returns a copy of str with all trailing
80
        /// whitespace removed.
81
{
82
        int pos = int(str.size()) - 1;
83
                
84
        while (pos >= 0 && std::isspace(str[pos])) --pos;
85
        return S(str, 0, pos + 1);
86
}
87
88
89
template <class S>
90
S& trimRightInPlace(S& str)
91
        /// Removes all trailing whitespace in str.
92
{
93
        int pos = int(str.size()) - 1;
94
                
95
        while (pos >= 0 && std::isspace(str[pos])) --pos;
96
        str.resize(pos + 1);
97
98
        return str;
99
}
100
101
102
template <class S>
103
S trim(const S& str)
104
        /// Returns a copy of str with all leading and
105
        /// trailing whitespace removed.
106
{
107
        int first = 0;
108
        int last  = int(str.size()) - 1;
109
        
110
        while (first <= last && std::isspace(str[first])) ++first;
111
        while (last >= first && std::isspace(str[last])) --last;
112
113
        return S(str, first, last - first + 1);
114
}
115
116
117
template <class S>
118
S& trimInPlace(S& str)
119
        /// Removes all leading and trailing whitespace in str.
120
{
121
        int first = 0;
122
        int last  = int(str.size()) - 1;
123
        
124
        while (first <= last && std::isspace(str[first])) ++first;
125
        while (last >= first && std::isspace(str[last])) --last;
126
127
        str.resize(last + 1);
128
        str.erase(0, first);
129
130
        return str;
131
}
132
133
134
template <class S>
135
S toUpper(const S& str)
136
        /// Returns a copy of str containing all upper-case characters.
137
{
138
        typename S::const_iterator it  = str.begin();
139
        typename S::const_iterator end = str.end();
140
141
        S result;
142
        result.reserve(str.size());
143
        while (it != end) result += std::toupper(*it++);
144
        return result;
145
}
146
147
148
template <class S>
149
S& toUpperInPlace(S& str)
150
        /// Replaces all characters in str with their upper-case counterparts.
151
{
152
        typename S::iterator it  = str.begin();
153
        typename S::iterator end = str.end();
154
155
        while (it != end) { *it = std::toupper(*it); ++it; }
156
        return str;
157
}
158
159
160
template <class S>
161
S toLower(const S& str)
162
        /// Returns a copy of str containing all lower-case characters.
163
{
164
        typename S::const_iterator it  = str.begin();
165
        typename S::const_iterator end = str.end();
166
167
        S result;
168
        result.reserve(str.size());
169
        while (it != end) result += std::tolower(*it++);
170
        return result;
171
}
172
173
174
template <class S>
175
S& toLowerInPlace(S& str)
176
        /// Replaces all characters in str with their lower-case counterparts.
177
{
178
        typename S::iterator it  = str.begin();
179
        typename S::iterator end = str.end();
180
181
        while (it != end) { *it = std::tolower(*it); ++it; }
182
        return str;
183
}
184
185
186
#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
187
188
189
template <class S, class It>
190
int icompare(
191
        const S& str,
192
        typename S::size_type pos, 
193
        typename S::size_type n,
194
        It it2, 
195
        It end2)
196
        /// Case-insensitive string comparison
197
{
198
        typename S::size_type sz = str.size();
199
        if (pos > sz) pos = sz;
200
        if (pos + n > sz) n = sz - pos;
201
        It it1  = str.begin() + pos; 
202
        It end1 = str.begin() + pos + n;
203
        while (it1 != end1 && it2 != end2)
204
        {
205
        typename S::value_type c1(std::tolower(*it1));
206
        typename S::value_type c2(std::tolower(*it2));
207
        if (c1 < c2)
208
            return -1;
209
        else if (c1 > c2)
210
            return 1;
211
        ++it1; ++it2;
212
        }
213
    
214
    if (it1 == end1)
215
                return it2 == end2 ? 0 : -1;
216
    else
217
        return 1;
218
}
219
220
221
template <class S>
222
int icompare(const S& str1, const S& str2)
223
{
224
        return icompare(str1, 0, str1.size(), str2.begin(), str2.end());
225
}
226
227
228
template <class S>
229
int icompare(const S& str1, typename S::size_type n1, const S& str2, typename S::size_type n2)
230
{
231
        if (n2 > str2.size()) n2 = str2.size();
232
        return icompare(str1, 0, n1, str2.begin(), str2.begin() + n2);
233
}
234
235
236
template <class S>
237
int icompare(const S& str1, typename S::size_type n, const S& str2)
238
{
239
        if (n > str2.size()) n = str2.size();
240
        return icompare(str1, 0, n, str2.begin(), str2.begin() + n);
241
}
242
243
244
template <class S>
245
int icompare(const S& str1, typename S::size_type pos, typename S::size_type n, const S& str2)
246
{
247
        return icompare(str1, pos, n, str2.begin(), str2.end());
248
}
249
250
251
template <class S>
252
int icompare(
253
        const S& str1, 
254
        typename S::size_type pos1, 
255
        typename S::size_type n1, 
256
        const S& str2,
257
        typename S::size_type pos2,
258
        typename S::size_type n2)
259
{
260
        typename S::size_type sz2 = str2.size();
261
        if (pos2 > sz2) pos2 = sz2;
262
        if (pos2 + n2 > sz2) n2 = sz2 - pos2;
263
        return icompare(str1, pos1, n1, str2.begin() + pos2, str2.begin() + pos2 + n2);
264
}
265
266
267
template <class S>
268
int icompare(
269
        const S& str1, 
270
        typename S::size_type pos1, 
271
        typename S::size_type n, 
272
        const S& str2,
273
        typename S::size_type pos2)
274
{
275
        typename S::size_type sz2 = str2.size();
276
        if (pos2 > sz2) pos2 = sz2;
277
        if (pos2 + n > sz2) n = sz2 - pos2;
278
        return icompare(str1, pos1, n, str2.begin() + pos2, str2.begin() + pos2 + n);
279
}
280
281
282
template <class S>
283
int icompare(
284
        const S& str,
285
        typename S::size_type pos,
286
        typename S::size_type n,
287
        const typename S::value_type* ptr)
288
{
289
        poco_check_ptr (ptr);
290
        typename S::size_type sz = str.size();
291
        if (pos > sz) pos = sz;
292
        if (pos + n > sz) n = sz - pos;
293
        typename S::const_iterator it  = str.begin() + pos; 
294
        typename S::const_iterator end = str.begin() + pos + n;
295
        while (it != end && *ptr)
296
        {
297
        typename S::value_type c1(std::tolower(*it));
298
        typename S::value_type c2(std::tolower(*ptr));
299
        if (c1 < c2)
300
            return -1;
301
        else if (c1 > c2)
302
            return 1;
303
        ++it; ++ptr;
304
        }
305
    
306
    if (it == end)
307
                return *ptr == 0 ? 0 : -1;
308
    else
309
        return 1;
310
}
311
312
313
template <class S>
314
int icompare(
315
        const S& str,
316
        typename S::size_type pos,
317
        const typename S::value_type* ptr)
318
{
319
        return icompare(str, pos, str.size() - pos, ptr);
320
}
321
322
323
template <class S>
324
int icompare(
325
        const S& str,
326
        const typename S::value_type* ptr)
327
{
328
        return icompare(str, 0, str.size(), ptr);
329
}
330
331
332
#else
333
334
335
int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2);
336
int Foundation_API icompare(const std::string& str1, const std::string& str2);
337
int Foundation_API icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2);
338
int Foundation_API icompare(const std::string& str1, std::string::size_type n, const std::string& str2);
339
int Foundation_API icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2);
340
int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n1, const std::string& str2, std::string::size_type pos2, std::string::size_type n2);
341
int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n, const std::string& str2, std::string::size_type pos2);
342
int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr);
343
int Foundation_API icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr);
344
int Foundation_API icompare(const std::string& str, const std::string::value_type* ptr);
345
346
347
#endif
348
349
350
template <class S>
351
S translate(const S& str, const S& from, const S& to)
352
        /// Returns a copy of str with all characters in
353
        /// from replaced by the corresponding (by position)
354
        /// characters in to. If there is no corresponding
355
        /// character in to, the character is removed from
356
        /// the copy. 
357
{
358
        S result;
359
        result.reserve(str.size());
360
        typename S::const_iterator it  = str.begin();
361
        typename S::const_iterator end = str.end();
362
        typename S::size_type toSize = to.size();
363
        while (it != end)
364
        {
365
                typename S::size_type pos = from.find(*it);
366
                if (pos == S::npos)
367
                {
368
                        result += *it;
369
                }
370
                else
371
                {
372
                        if (pos < toSize) result += to[pos];
373
                }
374
                ++it;
375
        }
376
        return result;
377
}
378
379
380
template <class S>
381
S translate(const S& str, const typename S::value_type* from, const typename S::value_type* to)
382
{
383
        poco_check_ptr (from);
384
        poco_check_ptr (to);
385
        return translate(str, S(from), S(to));
386
}
387
388
389
template <class S>
390
S& translateInPlace(S& str, const S& from, const S& to)
391
        /// Replaces in str all occurences of characters in from
392
        /// with the corresponding (by position) characters in to.
393
        /// If there is no corresponding character, the character
394
        /// is removed.
395
{
396
        str = translate(str, from, to);
397
        return str;
398
}
399
400
401
template <class S>
402
S translateInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to)
403
{
404
        poco_check_ptr (from);
405
        poco_check_ptr (to);
406
        str = translate(str, S(from), S(to));
407
        return str;
408
}
409
410
411
#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
412
413
414
template <class S>
415
S replace(const S& str, const S& from, const S& to, typename S::size_type start = 0)
416
        /// Replace all occurences of from (which must not be the empty string)
417
        /// in str with to, starting at position start.
418
{
419
        S result(str);
420
        replaceInPlace(result, from, to, start);
421
        return result;
422
}
423
424
425
template <class S>
426
S replace(const S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
427
{
428
        S result(str);
429
        replaceInPlace(result, from, to, start);
430
        return result;
431
}
432
433
434
template <class S>
435
S& replaceInPlace(S& str, const S& from, const S& to, typename S::size_type start = 0)
436
{
437
        poco_assert (from.size() > 0);
438
        
439
        S result;
440
        typename S::size_type pos = 0;
441
        result.append(str, 0, start);
442
        do
443
        {
444
                pos = str.find(from, start);
445
                if (pos != S::npos)
446
                {
447
                        result.append(str, start, pos - start);
448
                        result.append(to);
449
                        start = pos + from.length();
450
                }
451
                else result.append(str, start, str.size() - start);
452
        }
453
        while (pos != S::npos);
454
        str.swap(result);
455
        return str;
456
}
457
458
459
template <class S>
460
S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
461
{
462
        poco_assert (*from);
463
464
        S result;
465
        typename S::size_type pos = 0;
466
        typename S::size_type fromLen = std::strlen(from);
467
        result.append(str, 0, start);
468
        do
469
        {
470
                pos = str.find(from, start);
471
                if (pos != S::npos)
472
                {
473
                        result.append(str, start, pos - start);
474
                        result.append(to);
475
                        start = pos + fromLen;
476
                }
477
                else result.append(str, start, str.size() - start);
478
        }
479
        while (pos != S::npos);
480
        str.swap(result);
481
        return str;
482
}
483
484
485
#else
486
487
488
std::string Foundation_API replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
489
std::string Foundation_API replace(const std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
490
std::string& Foundation_API replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
491
std::string& Foundation_API replaceInPlace(std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
492
        
493
494
#endif        
495
496
497
template <class S>
498
S cat(const S& s1, const S& s2)
499
        /// Concatenates two strings.
500
{
501
        S result = s1;
502
        result.reserve(s1.size() + s2.size());
503
        result.append(s2);
504
        return result;
505
}
506
507
508
template <class S>
509
S cat(const S& s1, const S& s2, const S& s3)
510
        /// Concatenates three strings.
511
{
512
        S result = s1;
513
        result.reserve(s1.size() + s2.size() + s3.size());
514
        result.append(s2);
515
        result.append(s3);
516
        return result;
517
}
518
519
520
template <class S>
521
S cat(const S& s1, const S& s2, const S& s3, const S& s4)
522
        /// Concatenates four strings.
523
{
524
        S result = s1;
525
        result.reserve(s1.size() + s2.size() + s3.size() + s4.size());
526
        result.append(s2);
527
        result.append(s3);
528
        result.append(s4);
529
        return result;
530
}
531
532
533
template <class S>
534
S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5)
535
        /// Concatenates five strings.
536
{
537
        S result = s1;
538
        result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size());
539
        result.append(s2);
540
        result.append(s3);
541
        result.append(s4);
542
        result.append(s5);
543
        return result;
544
}
545
546
547
template <class S>
548
S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5, const S& s6)
549
        /// Concatenates six strings.
550
{
551
        S result = s1;
552
        result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size());
553
        result.append(s2);
554
        result.append(s3);
555
        result.append(s4);
556
        result.append(s5);
557
        result.append(s6);
558
        return result;
559
}
560
561
562
template <class S, class It>
563
S cat(const S& delim, const It& begin, const It& end)
564
        /// Concatenates a sequence of strings, delimited
565
        /// by the string given in delim.
566
{
567
        S result;
568
        for (It it = begin; it != end; ++it)
569
        {
570
                if (!result.empty()) result.append(delim);
571
                result += *it;
572
        }
573
        return result;
574
}
575
576
577
} // namespace Poco
578
579
580
#endif // Foundation_String_INCLUDED