~ubuntu-branches/ubuntu/gutsy/poco/gutsy

« back to all changes in this revision

Viewing changes to Foundation/include/Poco/String.h

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2007-04-27 18:33:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070427183348-xgnpct0qd6a2ip34
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// String.h
 
3
//
 
4
// $Id: //poco/1.2/Foundation/include/Poco/String.h#2 $
 
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 <locale>
 
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
        std::locale loc;
 
57
        typename S::const_iterator it  = str.begin();
 
58
        typename S::const_iterator end = str.end();
 
59
        
 
60
        while (it != end && isspace(*it, loc)) ++it;
 
61
        return S(it, end);
 
62
}
 
63
 
 
64
 
 
65
template <class S>
 
66
S& trimLeftInPlace(S& str)
 
67
        /// Removes all leading whitespace in str.
 
68
{
 
69
        std::locale loc;
 
70
        typename S::iterator it  = str.begin();
 
71
        typename S::iterator end = str.end();
 
72
        
 
73
        while (it != end && isspace(*it, loc)) ++it;
 
74
        str.erase(str.begin(), it);
 
75
        return str;
 
76
}
 
77
 
 
78
 
 
79
template <class S>
 
80
S trimRight(const S& str)
 
81
        /// Returns a copy of str with all trailing
 
82
        /// whitespace removed.
 
83
{
 
84
        std::locale loc;
 
85
        int pos = int(str.size()) - 1;
 
86
                
 
87
        while (pos >= 0 && isspace(str[pos], loc)) --pos;
 
88
        return S(str, 0, pos + 1);
 
89
}
 
90
 
 
91
 
 
92
template <class S>
 
93
S& trimRightInPlace(S& str)
 
94
        /// Removes all trailing whitespace in str.
 
95
{
 
96
        std::locale loc;
 
97
        int pos = int(str.size()) - 1;
 
98
                
 
99
        while (pos >= 0 && isspace(str[pos], loc)) --pos;
 
100
        str.resize(pos + 1);
 
101
 
 
102
        return str;
 
103
}
 
104
 
 
105
 
 
106
template <class S>
 
107
S trim(const S& str)
 
108
        /// Returns a copy of str with all leading and
 
109
        /// trailing whitespace removed.
 
110
{
 
111
        std::locale loc;
 
112
        int first = 0;
 
113
        int last  = int(str.size()) - 1;
 
114
        
 
115
        while (first <= last && isspace(str[first], loc)) ++first;
 
116
        while (last >= first && isspace(str[last], loc)) --last;
 
117
 
 
118
        return S(str, first, last - first + 1);
 
119
}
 
120
 
 
121
 
 
122
template <class S>
 
123
S& trimInPlace(S& str)
 
124
        /// Removes all leading and trailing whitespace in str.
 
125
{
 
126
        std::locale loc;
 
127
        int first = 0;
 
128
        int last  = int(str.size()) - 1;
 
129
        
 
130
        while (first <= last && isspace(str[first], loc)) ++first;
 
131
        while (last >= first && isspace(str[last], loc)) --last;
 
132
 
 
133
        str.resize(last + 1);
 
134
        str.erase(0, first);
 
135
 
 
136
        return str;
 
137
}
 
138
 
 
139
 
 
140
template <class S>
 
141
S toUpper(const S& str)
 
142
        /// Returns a copy of str containing all upper-case characters.
 
143
{
 
144
        std::locale loc;
 
145
        typename S::const_iterator it  = str.begin();
 
146
        typename S::const_iterator end = str.end();
 
147
 
 
148
        S result;
 
149
        result.reserve(str.size());
 
150
        while (it != end) result += toupper(*it++, loc);
 
151
        return result;
 
152
}
 
153
 
 
154
 
 
155
template <class S>
 
156
S& toUpperInPlace(S& str)
 
157
        /// Replaces all characters in str with their upper-case counterparts.
 
158
{
 
159
        std::locale loc;
 
160
        typename S::iterator it  = str.begin();
 
161
        typename S::iterator end = str.end();
 
162
 
 
163
        while (it != end) { *it = toupper(*it, loc); ++it; }
 
164
        return str;
 
165
}
 
166
 
 
167
 
 
168
template <class S>
 
169
S toLower(const S& str)
 
170
        /// Returns a copy of str containing all lower-case characters.
 
171
{
 
172
        std::locale loc;
 
173
        typename S::const_iterator it  = str.begin();
 
174
        typename S::const_iterator end = str.end();
 
175
 
 
176
        S result;
 
177
        result.reserve(str.size());
 
178
        while (it != end) result += tolower(*it++, loc);
 
179
        return result;
 
180
}
 
181
 
 
182
 
 
183
template <class S>
 
184
S& toLowerInPlace(S& str)
 
185
        /// Replaces all characters in str with their lower-case counterparts.
 
186
{
 
187
        std::locale loc;
 
188
        typename S::iterator it  = str.begin();
 
189
        typename S::iterator end = str.end();
 
190
 
 
191
        while (it != end) { *it = tolower(*it, loc); ++it; }
 
192
        return str;
 
193
}
 
194
 
 
195
 
 
196
#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
 
197
 
 
198
 
 
199
template <class S, class It>
 
200
int icompare(
 
201
        const S& str,
 
202
        typename S::size_type pos, 
 
203
        typename S::size_type n,
 
204
        It it2, 
 
205
        It end2)
 
206
        /// Case-insensitive string comparison
 
207
{
 
208
        typename S::size_type sz = str.size();
 
209
        if (pos > sz) pos = sz;
 
210
        if (pos + n > sz) n = sz - pos;
 
211
        It it1  = str.begin() + pos; 
 
212
        It end1 = str.begin() + pos + n;
 
213
        std::locale loc;
 
214
        while (it1 != end1 && it2 != end2)
 
215
        {
 
216
        typename S::value_type c1 = tolower(*it1, loc);
 
217
        typename S::value_type c2 = tolower(*it2, loc);
 
218
        if (c1 < c2)
 
219
            return -1;
 
220
        else if (c1 > c2)
 
221
            return 1;
 
222
        ++it1; ++it2;
 
223
        }
 
224
    
 
225
    if (it1 == end1)
 
226
                return it2 == end2 ? 0 : -1;
 
227
    else
 
228
        return 1;
 
229
}
 
230
 
 
231
 
 
232
template <class S>
 
233
int icompare(const S& str1, const S& str2)
 
234
{
 
235
        return icompare(str1, 0, str1.size(), str2.begin(), str2.end());
 
236
}
 
237
 
 
238
 
 
239
template <class S>
 
240
int icompare(const S& str1, typename S::size_type n1, const S& str2, typename S::size_type n2)
 
241
{
 
242
        if (n2 > str2.size()) n2 = str2.size();
 
243
        return icompare(str1, 0, n1, str2.begin(), str2.begin() + n2);
 
244
}
 
245
 
 
246
 
 
247
template <class S>
 
248
int icompare(const S& str1, typename S::size_type n, const S& str2)
 
249
{
 
250
        if (n > str2.size()) n = str2.size();
 
251
        return icompare(str1, 0, n, str2.begin(), str2.begin() + n);
 
252
}
 
253
 
 
254
 
 
255
template <class S>
 
256
int icompare(const S& str1, typename S::size_type pos, typename S::size_type n, const S& str2)
 
257
{
 
258
        return icompare(str1, pos, n, str2.begin(), str2.end());
 
259
}
 
260
 
 
261
 
 
262
template <class S>
 
263
int icompare(
 
264
        const S& str1, 
 
265
        typename S::size_type pos1, 
 
266
        typename S::size_type n1, 
 
267
        const S& str2,
 
268
        typename S::size_type pos2,
 
269
        typename S::size_type n2)
 
270
{
 
271
        typename S::size_type sz2 = str2.size();
 
272
        if (pos2 > sz2) pos2 = sz2;
 
273
        if (pos2 + n2 > sz2) n2 = sz2 - pos2;
 
274
        return icompare(str1, pos1, n1, str2.begin() + pos2, str2.begin() + pos2 + n2);
 
275
}
 
276
 
 
277
 
 
278
template <class S>
 
279
int icompare(
 
280
        const S& str1, 
 
281
        typename S::size_type pos1, 
 
282
        typename S::size_type n, 
 
283
        const S& str2,
 
284
        typename S::size_type pos2)
 
285
{
 
286
        typename S::size_type sz2 = str2.size();
 
287
        if (pos2 > sz2) pos2 = sz2;
 
288
        if (pos2 + n > sz2) n = sz2 - pos2;
 
289
        return icompare(str1, pos1, n, str2.begin() + pos2, str2.begin() + pos2 + n);
 
290
}
 
291
 
 
292
 
 
293
template <class S>
 
294
int icompare(
 
295
        const S& str,
 
296
        typename S::size_type pos,
 
297
        typename S::size_type n,
 
298
        const typename S::value_type* ptr)
 
299
{
 
300
        poco_check_ptr (ptr);
 
301
        typename S::size_type sz = str.size();
 
302
        if (pos > sz) pos = sz;
 
303
        if (pos + n > sz) n = sz - pos;
 
304
        typename S::const_iterator it  = str.begin() + pos; 
 
305
        typename S::const_iterator end = str.begin() + pos + n;
 
306
        std::locale loc;
 
307
        while (it != end && *ptr)
 
308
        {
 
309
        typename S::value_type c1 = tolower(*it, loc);
 
310
        typename S::value_type c2 = tolower(*ptr, loc);
 
311
        if (c1 < c2)
 
312
            return -1;
 
313
        else if (c1 > c2)
 
314
            return 1;
 
315
        ++it; ++ptr;
 
316
        }
 
317
    
 
318
    if (it == end)
 
319
                return *ptr == 0 ? 0 : -1;
 
320
    else
 
321
        return 1;
 
322
}
 
323
 
 
324
 
 
325
template <class S>
 
326
int icompare(
 
327
        const S& str,
 
328
        typename S::size_type pos,
 
329
        const typename S::value_type* ptr)
 
330
{
 
331
        return icompare(str, pos, str.size() - pos, ptr);
 
332
}
 
333
 
 
334
 
 
335
template <class S>
 
336
int icompare(
 
337
        const S& str,
 
338
        const typename S::value_type* ptr)
 
339
{
 
340
        return icompare(str, 0, str.size(), ptr);
 
341
}
 
342
 
 
343
 
 
344
#else
 
345
 
 
346
 
 
347
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);
 
348
int Foundation_API icompare(const std::string& str1, const std::string& str2);
 
349
int Foundation_API icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2);
 
350
int Foundation_API icompare(const std::string& str1, std::string::size_type n, const std::string& str2);
 
351
int Foundation_API icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2);
 
352
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);
 
353
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);
 
354
int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr);
 
355
int Foundation_API icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr);
 
356
int Foundation_API icompare(const std::string& str, const std::string::value_type* ptr);
 
357
 
 
358
 
 
359
#endif
 
360
 
 
361
 
 
362
template <class S>
 
363
S translate(const S& str, const S& from, const S& to)
 
364
        /// Returns a copy of str with all characters in
 
365
        /// from replaced by the corresponding (by position)
 
366
        /// characters in to. If there is no corresponding
 
367
        /// character in to, the character is removed from
 
368
        /// the copy. 
 
369
{
 
370
        S result;
 
371
        result.reserve(str.size());
 
372
        typename S::const_iterator it  = str.begin();
 
373
        typename S::const_iterator end = str.end();
 
374
        typename S::size_type toSize = to.size();
 
375
        while (it != end)
 
376
        {
 
377
                typename S::size_type pos = from.find(*it);
 
378
                if (pos == S::npos)
 
379
                {
 
380
                        result += *it;
 
381
                }
 
382
                else
 
383
                {
 
384
                        if (pos < toSize) result += to[pos];
 
385
                }
 
386
                ++it;
 
387
        }
 
388
        return result;
 
389
}
 
390
 
 
391
 
 
392
template <class S>
 
393
S translate(const S& str, const typename S::value_type* from, const typename S::value_type* to)
 
394
{
 
395
        poco_check_ptr (from);
 
396
        poco_check_ptr (to);
 
397
        return translate(str, S(from), S(to));
 
398
}
 
399
 
 
400
 
 
401
template <class S>
 
402
S& translateInPlace(S& str, const S& from, const S& to)
 
403
        /// Replaces in str all occurences of characters in from
 
404
        /// with the corresponding (by position) characters in to.
 
405
        /// If there is no corresponding character, the character
 
406
        /// is removed.
 
407
{
 
408
        str = translate(str, from, to);
 
409
        return str;
 
410
}
 
411
 
 
412
 
 
413
template <class S>
 
414
S translateInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to)
 
415
{
 
416
        poco_check_ptr (from);
 
417
        poco_check_ptr (to);
 
418
        str = translate(str, S(from), S(to));
 
419
        return str;
 
420
}
 
421
 
 
422
 
 
423
#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
 
424
 
 
425
 
 
426
template <class S>
 
427
S replace(const S& str, const S& from, const S& to, typename S::size_type start = 0)
 
428
        /// Replace all occurences of from (which must not be the empty string)
 
429
        /// in str with to, starting at position start.
 
430
{
 
431
        S result(str);
 
432
        replaceInPlace(result, from, to, start);
 
433
        return result;
 
434
}
 
435
 
 
436
 
 
437
template <class S>
 
438
S replace(const S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
 
439
{
 
440
        S result(str);
 
441
        replaceInPlace(result, from, to, start);
 
442
        return result;
 
443
}
 
444
 
 
445
 
 
446
template <class S>
 
447
S& replaceInPlace(S& str, const S& from, const S& to, typename S::size_type start = 0)
 
448
{
 
449
        poco_assert (from.size() > 0);
 
450
        
 
451
        S result;
 
452
        typename S::size_type pos = 0;
 
453
        result.append(str, 0, start);
 
454
        do
 
455
        {
 
456
                pos = str.find(from, start);
 
457
                if (pos != S::npos)
 
458
                {
 
459
                        result.append(str, start, pos - start);
 
460
                        result.append(to);
 
461
                        start = pos + from.length();
 
462
                }
 
463
                else result.append(str, start, str.size() - start);
 
464
        }
 
465
        while (pos != S::npos);
 
466
        str.swap(result);
 
467
        return str;
 
468
}
 
469
 
 
470
 
 
471
template <class S>
 
472
S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
 
473
{
 
474
        poco_assert (*from);
 
475
 
 
476
        S result;
 
477
        typename S::size_type pos = 0;
 
478
        typename S::size_type fromLen = strlen(from);
 
479
        result.append(str, 0, start);
 
480
        do
 
481
        {
 
482
                pos = str.find(from, start);
 
483
                if (pos != S::npos)
 
484
                {
 
485
                        result.append(str, start, pos - start);
 
486
                        result.append(to);
 
487
                        start = pos + fromLen;
 
488
                }
 
489
                else result.append(str, start, str.size() - start);
 
490
        }
 
491
        while (pos != S::npos);
 
492
        str.swap(result);
 
493
        return str;
 
494
}
 
495
 
 
496
 
 
497
#else
 
498
 
 
499
 
 
500
std::string Foundation_API replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
 
501
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);
 
502
std::string& Foundation_API replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
 
503
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);
 
504
        
 
505
 
 
506
#endif  
 
507
 
 
508
 
 
509
template <class S>
 
510
S cat(const S& s1, const S& s2)
 
511
        /// Concatenates two strings.
 
512
{
 
513
        S result = s1;
 
514
        result.reserve(s1.size() + s2.size());
 
515
        result.append(s2);
 
516
        return result;
 
517
}
 
518
 
 
519
 
 
520
template <class S>
 
521
S cat(const S& s1, const S& s2, const S& s3)
 
522
        /// Concatenates three strings.
 
523
{
 
524
        S result = s1;
 
525
        result.reserve(s1.size() + s2.size() + s3.size());
 
526
        result.append(s2);
 
527
        result.append(s3);
 
528
        return result;
 
529
}
 
530
 
 
531
 
 
532
template <class S>
 
533
S cat(const S& s1, const S& s2, const S& s3, const S& s4)
 
534
        /// Concatenates four strings.
 
535
{
 
536
        S result = s1;
 
537
        result.reserve(s1.size() + s2.size() + s3.size() + s4.size());
 
538
        result.append(s2);
 
539
        result.append(s3);
 
540
        result.append(s4);
 
541
        return result;
 
542
}
 
543
 
 
544
 
 
545
template <class S>
 
546
S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5)
 
547
        /// Concatenates five strings.
 
548
{
 
549
        S result = s1;
 
550
        result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size());
 
551
        result.append(s2);
 
552
        result.append(s3);
 
553
        result.append(s4);
 
554
        result.append(s5);
 
555
        return result;
 
556
}
 
557
 
 
558
 
 
559
template <class S>
 
560
S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5, const S& s6)
 
561
        /// Concatenates six strings.
 
562
{
 
563
        S result = s1;
 
564
        result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size());
 
565
        result.append(s2);
 
566
        result.append(s3);
 
567
        result.append(s4);
 
568
        result.append(s5);
 
569
        result.append(s6);
 
570
        return result;
 
571
}
 
572
 
 
573
 
 
574
template <class S, class It>
 
575
S cat(const S& delim, const It& begin, const It& end)
 
576
        /// Concatenates a sequence of strings, delimited
 
577
        /// by the string given in delim.
 
578
{
 
579
        S result;
 
580
        for (It it = begin; it != end; ++it)
 
581
        {
 
582
                if (!result.empty()) result.append(delim);
 
583
                result += *it;
 
584
        }
 
585
        return result;
 
586
}
 
587
 
 
588
 
 
589
} // namespace Poco
 
590
 
 
591
 
 
592
#endif // Foundation_String_INCLUDED