1 mike 1.27 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.41 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
|
5 mike 1.27 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 kumpf 1.41 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
10 mike 1.27 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
|
13 kumpf 1.41 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
14 mike 1.27 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
16 kumpf 1.41 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19 mike 1.27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
24 // Author: Mike Brasher (mbrasher@bmc.com)
25 //
|
26 kumpf 1.39 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
27 mike 1.27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30
31 #include <cctype>
32 #include "String.h"
|
33 kumpf 1.43 #include "Array.h"
|
34 kumpf 1.48 #include "InternalException.h"
|
35 mike 1.27 #include <iostream>
36
|
37 mike 1.28 PEGASUS_USING_STD;
38
|
39 mike 1.27 PEGASUS_NAMESPACE_BEGIN
40
|
41 kumpf 1.39 ///////////////////////////////////////////////////////////////////////////////
42 //
|
43 kumpf 1.54 // CString
44 //
45 ///////////////////////////////////////////////////////////////////////////////
46
47 CString::CString()
48 : _rep(0)
49 {
50 }
51
52 CString::CString(const CString& cstr)
53 {
54 _rep = new char[strlen(cstr._rep)+1];
55 _rep = strcpy(_rep, cstr._rep);
56 }
57
58 CString::CString(char* cstr)
59 : _rep(cstr)
60 {
61 }
62
63 CString::~CString()
64 kumpf 1.54 {
65 if (_rep)
66 delete [] _rep;
67 }
68
|
69 kumpf 1.56 CString& CString::operator=(const CString& cstr)
70 {
71 _rep = new char[strlen(cstr._rep)+1];
72 _rep = strcpy(_rep, cstr._rep);
73 return *this;
74 }
75
|
76 kumpf 1.54 CString::operator const char*() const
77 {
78 return _rep;
79 }
80
81 ///////////////////////////////////////////////////////////////////////////////
82 //
|
83 kumpf 1.39 // String
84 //
85 ///////////////////////////////////////////////////////////////////////////////
86
|
87 kumpf 1.37 const String String::EMPTY = String();
|
88 mike 1.27
|
89 kumpf 1.38 Uint32 _strnlen(const char* str, Uint32 n)
90 {
91 if (!str)
92 throw NullPointer();
93
94 for (Uint32 i=0; i<n; i++)
95 {
96 if (!*str)
97 {
98 return i;
99 }
100 }
101
102 return n;
103 }
104
105 Uint32 _strnlen(const Char16* str, Uint32 n)
106 {
107 if (!str)
108 throw NullPointer();
109
110 kumpf 1.38 for (Uint32 i=0; i<n; i++)
111 {
112 if (!*str)
113 {
114 return i;
115 }
116 }
117
118 return n;
119 }
120
|
121 kumpf 1.39 inline Uint32 _StrLen(const char* str)
|
122 mike 1.27 {
123 if (!str)
124 throw NullPointer();
125
126 return strlen(str);
127 }
128
|
129 kumpf 1.39 inline Uint32 _StrLen(const Char16* str)
|
130 mike 1.27 {
131 if (!str)
132 throw NullPointer();
133
134 Uint32 n = 0;
135
136 while (*str++)
137 n++;
138
139 return n;
140 }
141
|
142 kumpf 1.43 class StringRep
143 {
144 public:
145 StringRep()
146 {}
147 StringRep(const StringRep& r)
148 : c16a(r.c16a)
149 {}
150 StringRep(const Char16* str)
151 : c16a(str, _StrLen(str) + 1)
152 {}
153
154 Array<Char16> c16a;
155 };
156
|
157 mike 1.27 String::String()
158 {
|
159 kumpf 1.43 _rep = new StringRep;
160 _rep->c16a.append('\0');
|
161 mike 1.27 }
162
|
163 kumpf 1.39 String::String(const String& str)
|
164 mike 1.27 {
|
165 kumpf 1.43 _rep = new StringRep(*str._rep);
|
166 kumpf 1.39 }
|
167 mike 1.27
|
168 kumpf 1.39 String::String(const String& str, Uint32 n)
169 {
|
170 kumpf 1.43 _rep = new StringRep;
|
171 kumpf 1.55 assign(str.getChar16Data(), n);
|
172 kumpf 1.39 }
173
174 String::String(const Char16* str)
175 {
|
176 kumpf 1.43 _rep = new StringRep(str);
|
177 mike 1.27 }
178
|
179 kumpf 1.39 String::String(const Char16* str, Uint32 n)
180 {
|
181 kumpf 1.43 _rep = new StringRep;
|
182 kumpf 1.39 assign(str, n);
183 }
184
185 String::String(const char* str)
|
186 mike 1.27 {
|
187 kumpf 1.43 _rep = new StringRep;
|
188 kumpf 1.39 assign(str);
|
189 mike 1.27 }
190
|
191 kumpf 1.39 String::String(const char* str, Uint32 n)
|
192 mike 1.27 {
|
193 kumpf 1.43 _rep = new StringRep;
|
194 kumpf 1.39 assign(str, n);
195 }
|
196 mike 1.27
|
197 kumpf 1.39 String::~String()
198 {
|
199 kumpf 1.43 delete _rep;
|
200 mike 1.27 }
201
|
202 kumpf 1.39 String& String::operator=(const String& str)
|
203 mike 1.27 {
|
204 kumpf 1.39 return assign(str);
|
205 mike 1.27 }
206
|
207 kumpf 1.39 String& String::assign(const String& str)
|
208 mike 1.27 {
|
209 kumpf 1.43 _rep->c16a = str._rep->c16a;
|
210 kumpf 1.39 return *this;
|
211 mike 1.27 }
212
|
213 kumpf 1.39 String& String::assign(const Char16* str)
|
214 mike 1.27 {
|
215 kumpf 1.43 _rep->c16a.clear();
216 _rep->c16a.append(str, _StrLen(str) + 1);
|
217 mike 1.27 return *this;
218 }
219
220 String& String::assign(const Char16* str, Uint32 n)
221 {
|
222 kumpf 1.43 _rep->c16a.clear();
|
223 kumpf 1.38 Uint32 m = _strnlen(str, n);
|
224 kumpf 1.43 _rep->c16a.append(str, m);
225 _rep->c16a.append('\0');
|
226 mike 1.27 return *this;
227 }
228
|
229 kumpf 1.39 String& String::assign(const char* str)
|
230 mike 1.27 {
|
231 kumpf 1.43 _rep->c16a.clear();
|
232 kumpf 1.38
|
233 kumpf 1.39 Uint32 n = strlen(str) + 1;
|
234 kumpf 1.45 _rep->c16a.reserveCapacity(n);
|
235 mike 1.27
236 while (n--)
|
237 kumpf 1.43 _rep->c16a.append(*str++);
|
238 mike 1.27
239 return *this;
240 }
241
|
242 kumpf 1.39 String& String::assign(const char* str, Uint32 n)
|
243 mike 1.27 {
|
244 kumpf 1.43 _rep->c16a.clear();
|
245 mike 1.27
|
246 kumpf 1.39 Uint32 _n = _strnlen(str, n);
|
247 kumpf 1.45 _rep->c16a.reserveCapacity(_n + 1);
|
248 mike 1.27
|
249 kumpf 1.39 while (_n--)
|
250 kumpf 1.43 _rep->c16a.append(*str++);
|
251 mike 1.27
|
252 kumpf 1.43 _rep->c16a.append('\0');
|
253 mike 1.27
254 return *this;
255 }
256
|
257 kumpf 1.39 void String::clear()
258 {
|
259 kumpf 1.43 _rep->c16a.clear();
260 _rep->c16a.append('\0');
|
261 kumpf 1.39 }
262
|
263 kumpf 1.43 void String::reserveCapacity(Uint32 capacity)
|
264 kumpf 1.39 {
|
265 kumpf 1.45 _rep->c16a.reserveCapacity(capacity + 1);
|
266 kumpf 1.39 }
267
268 Uint32 String::size() const
269 {
|
270 kumpf 1.43 return _rep->c16a.size() - 1;
|
271 kumpf 1.39 }
272
|
273 kumpf 1.55 const Char16* String::getChar16Data() const
|
274 kumpf 1.39 {
|
275 kumpf 1.43 return _rep->c16a.getData();
|
276 kumpf 1.39 }
277
|
278 kumpf 1.54 CString String::getCString() const
|
279 mike 1.27 {
280 Uint32 n = size() + 1;
|
281 kumpf 1.54 char* str = new char[n];
|
282 mike 1.27 char* p = str;
|
283 kumpf 1.55 const Char16* q = getChar16Data();
|
284 mike 1.27
285 for (Uint32 i = 0; i < n; i++)
286 {
287 Uint16 c = *q++;
288 *p++ = char(c);
289
|
290 kumpf 1.54 //if (c & 0xff00)
291 // truncatedCharacters = true;
|
292 mike 1.27 }
293
|
294 kumpf 1.54 return CString(str);
|
295 kumpf 1.49 }
296
|
297 kumpf 1.53 Char16& String::operator[](Uint32 index)
|
298 mike 1.27 {
|
299 kumpf 1.53 if (index > size())
|
300 kumpf 1.49 throw IndexOutOfBoundsException();
|
301 mike 1.27
|
302 kumpf 1.53 return _rep->c16a[index];
|
303 mike 1.27 }
304
|
305 kumpf 1.53 const Char16 String::operator[](Uint32 index) const
|
306 mike 1.27 {
|
307 kumpf 1.53 if (index > size())
|
308 kumpf 1.49 throw IndexOutOfBoundsException();
|
309 mike 1.27
|
310 kumpf 1.53 return _rep->c16a[index];
|
311 mike 1.27 }
312
|
313 kumpf 1.39 String& String::append(const Char16& c)
314 {
|
315 kumpf 1.43 _rep->c16a.insert(_rep->c16a.size() - 1, c);
|
316 kumpf 1.39 return *this;
317 }
318
|
319 mike 1.27 String& String::append(const Char16* str, Uint32 n)
320 {
|
321 kumpf 1.38 Uint32 m = _strnlen(str, n);
|
322 kumpf 1.45 _rep->c16a.reserveCapacity(_rep->c16a.size() + m);
|
323 kumpf 1.43 _rep->c16a.remove(_rep->c16a.size() - 1);
324 _rep->c16a.append(str, m);
325 _rep->c16a.append('\0');
|
326 mike 1.27 return *this;
327 }
328
|
329 kumpf 1.39 String& String::append(const String& str)
|
330 mike 1.27 {
|
331 kumpf 1.55 return append(str.getChar16Data(), str.size());
|
332 mike 1.27 }
333
|
334 kumpf 1.53 void String::remove(Uint32 index, Uint32 size)
|
335 mike 1.27 {
|
336 kumpf 1.39 if (size == PEG_NOT_FOUND)
|
337 kumpf 1.53 size = this->size() - index;
|
338 mike 1.27
|
339 kumpf 1.53 if (index + size > this->size())
|
340 kumpf 1.49 throw IndexOutOfBoundsException();
|
341 mike 1.27
|
342 kumpf 1.39 if (size)
|
343 kumpf 1.53 _rep->c16a.remove(index, size);
|
344 mike 1.27 }
345
|
346 kumpf 1.53 String String::subString(Uint32 index, Uint32 length) const
|
347 mike 1.27 {
|
348 kumpf 1.53 if (index < size())
|
349 mike 1.27 {
350 if (length == PEG_NOT_FOUND)
|
351 kumpf 1.53 length = size() - index;
|
352 mike 1.27
|
353 kumpf 1.55 return String(getChar16Data() + index, length);
|
354 mike 1.27 }
355 else
356 return String();
357 }
358
359 Uint32 String::find(Char16 c) const
360 {
|
361 kumpf 1.55 const Char16* first = getChar16Data();
|
362 mike 1.27
363 for (const Char16* p = first; *p; p++)
364 {
365 if (*p == c)
366 return p - first;
367 }
368
369 return PEG_NOT_FOUND;
370 }
371
|
372 kumpf 1.53 Uint32 String::find(Uint32 index, Char16 c) const
|
373 mike 1.30 {
|
374 kumpf 1.55 const Char16* data = getChar16Data();
|
375 mike 1.30
|
376 kumpf 1.53 for (Uint32 i = index, n = size(); i < n; i++)
|
377 mike 1.30 {
378 if (data[i] == c)
379 return i;
380 }
381
382 return PEG_NOT_FOUND;
383 }
384
|
385 mike 1.27 Uint32 String::find(const String& s) const
386 {
|
387 kumpf 1.55 const Char16* pSubStr = s.getChar16Data();
388 const Char16* pStr = getChar16Data();
|
389 mike 1.27 Uint32 subStrLen = s.size();
390 Uint32 strLen = size();
391
|
392 mike 1.30 if (subStrLen > strLen)
393 {
394 return PEG_NOT_FOUND;
395 }
396
|
397 mike 1.27 // loop to find first char match
398 Uint32 loc = 0;
399 for( ; loc <= (strLen-subStrLen); loc++)
400 {
401 if (*pStr++ == *pSubStr) // match first char
402 {
403 // point to substr 2nd char
404 const Char16* p = pSubStr + 1;
405
406 // Test remaining chars for equal
407 Uint32 i = 1;
408 for (; i < subStrLen; i++)
409 if (*pStr++ != *p++ )
410 {pStr--; break;} // break from loop
411 if (i == subStrLen)
412 return loc;
413 }
414 }
415 return PEG_NOT_FOUND;
416 }
417
418 mike 1.27 Uint32 String::reverseFind(Char16 c) const
419 {
|
420 kumpf 1.55 const Char16* first = getChar16Data();
421 const Char16* last = getChar16Data() + size();
|
422 mike 1.27
423 while (last != first)
424 {
425 if (*--last == c)
426 return last - first;
427 }
428
429 return PEG_NOT_FOUND;
430 }
431
432 void String::toLower()
433 {
|
434 kumpf 1.43 for (Char16* p = &_rep->c16a[0]; *p; p++)
|
435 mike 1.27 {
|
436 kumpf 1.46 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
|
437 mike 1.27 *p = tolower(*p);
438 }
|
439 kumpf 1.39 }
440
|
441 kumpf 1.43 int String::compare(const String& s1, const String& s2, Uint32 n)
|
442 kumpf 1.39 {
|
443 kumpf 1.55 const Char16* s1c16 = s1.getChar16Data();
444 const Char16* s2c16 = s2.getChar16Data();
|
445 kumpf 1.39
446 while (n--)
|
447 mike 1.27 {
|
448 kumpf 1.43 int r = *s1c16++ - *s2c16++;
|
449 mike 1.27
450 if (r)
451 return r;
452 }
453
454 return 0;
455 }
456
|
457 kumpf 1.43 int String::compare(const String& s1, const String& s2)
|
458 mike 1.30 {
|
459 kumpf 1.55 const Char16* s1c16 = s1.getChar16Data();
460 const Char16* s2c16 = s2.getChar16Data();
|
461 kumpf 1.43
462 while (*s1c16 && *s2c16)
|
463 mike 1.30 {
|
464 kumpf 1.43 int r = *s1c16++ - *s2c16++;
|
465 mike 1.30
466 if (r)
467 return r;
468 }
469
|
470 kumpf 1.43 if (*s2c16)
|
471 mike 1.30 return -1;
|
472 kumpf 1.43 else if (*s1c16)
|
473 mike 1.30 return 1;
474
475 return 0;
476 }
477
|
478 kumpf 1.40 int String::compareNoCase(const String& s1, const String& s2)
479 {
|
480 kumpf 1.55 const Char16* _s1 = s1.getChar16Data();
481 const Char16* _s2 = s2.getChar16Data();
|
482 kumpf 1.40
483 while (*_s1 && *_s2)
484 {
485 int r;
486
|
487 kumpf 1.46 if (*_s1 <= PEGASUS_MAX_PRINTABLE_CHAR &&
488 *_s2 <= PEGASUS_MAX_PRINTABLE_CHAR)
|
489 kumpf 1.40 {
490 r = tolower(*_s1++) - tolower(*_s2++);
491 }
492 else
493 {
494 r = *_s1++ - *_s2++;
495 }
496
497 if (r)
498 return r;
499 }
500
501 if (*_s2)
502 return -1;
503 else if (*_s1)
504 return 1;
505
506 return 0;
507 }
508
|
509 kumpf 1.39 Boolean String::equal(const String& str1, const String& str2)
|
510 mike 1.27 {
|
511 kumpf 1.43 return String::compare(str1, str2) == 0;
|
512 mike 1.27 }
513
|
514 kumpf 1.39 Boolean String::equalNoCase(const String& str1, const String& str2)
|
515 mike 1.27 {
|
516 kumpf 1.39 if (str1.size() != str2.size())
517 return false;
518
|
519 kumpf 1.55 const Char16* p = str1.getChar16Data();
520 const Char16* q = str2.getChar16Data();
|
521 kumpf 1.39
522 Uint32 n = str1.size();
|
523 mike 1.27
|
524 kumpf 1.39 while (n--)
525 {
|
526 kumpf 1.46 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR &&
527 *q <= PEGASUS_MAX_PRINTABLE_CHAR)
|
528 kumpf 1.39 {
529 if (tolower(*p++) != tolower(*q++))
530 return false;
531 }
532 else if (*p++ != *q++)
533 return false;
534 }
|
535 mike 1.28
|
536 kumpf 1.39 return true;
|
537 mike 1.27 }
538
|
539 kumpf 1.42
540 // ATTN-RK-P3-20020603: This code is not completely correct
|
541 karl 1.36 // Wildcard String matching function that may be useful in the future
542 // The following code was provided by Bob Blair.
543
544 /* _StringMatch Match input MatchString against a GLOB style pattern
545 Note that MatchChar is the char type so that this source
546 in portable to different string types. This is an internal function
547
548 Results: The return value is 1 if string matches pattern, and
549 0 otherwise. The matching operation permits the following
550 special characters in the pattern: *?\[] (see the manual
551 entry for details on what these mean).
552
553 Side effects: None.
554 */
555
556 /* MatchChar defined as a separate entity because this function source used
557 elsewhere was an unsigned char *. Here we use Uint16 to maintain 16 bit
558 size.
559 */
560 typedef Uint16 MatchChar;
561
562 karl 1.36 inline Uint16 _ToLower(Uint16 ch)
563 {
|
564 kumpf 1.46 return ch <= PEGASUS_MAX_PRINTABLE_CHAR ? tolower(char(ch)) : ch;
|
565 karl 1.36 }
566
567 inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
568 {
569 if (nocase)
570 return _ToLower(ch1) == _ToLower(ch2);
571 else
572 return ch1 == ch2;
573 }
|
574 mike 1.28
|
575 kumpf 1.35
|
576 karl 1.36 static const MatchChar *
577 _matchrange(const MatchChar *range, MatchChar c, int nocase)
578 {
579 const MatchChar *p = range;
580 const MatchChar *rstart = range + 1;
581 const MatchChar *rend = 0;
582 MatchChar compchar;
583
|
584 kumpf 1.35 for (rend = rstart; *rend && *rend != ']'; rend++);
|
585 karl 1.36 if (*rend == ']') { // if there is an end to this pattern
|
586 kumpf 1.35 for (compchar = *rstart; rstart != rend; rstart++) {
|
587 karl 1.36 if (_Equal(*rstart, c, nocase))
|
588 kumpf 1.35 return ++rend;
589 if (*rstart == '-') {
590 rstart++;
591 if (c >= compchar && c <= *rstart)
592 return ++rend;
593 }
594 }
595 }
|
596 karl 1.36 return (const MatchChar *)0;
|
597 kumpf 1.35 }
598
599 static int
|
600 karl 1.36 _StringMatch(
601 const MatchChar *testString,
602 const MatchChar *pattern,
603 int nocase ) /* Ignore case if this is true */
604 {
605 const MatchChar *pat = pattern;
606 const MatchChar *str = testString;
|
607 kumpf 1.35 unsigned int done = 0;
608 unsigned int res = 0; // the result: 1 == match
609
610 while (!done) { // main loop walks through pattern and test string
611 //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
612 if (!*pat) { //end of pattern
613 done = 1; // we're done
614 if (!*str) //end of test, too?
615 res = 1; // then we matched
616 } else { //Not end of pattern
617 if (!*str) { // but end of test
618 done = 1; // We're done
619 if (*pat == '*') // If pattern openends
620 res = 1; // then we matched
621 } else { //Not end of test
622 if (*pat == '*') { //Ambiguuity found
623 if (!*++pat) { //and it ends pattern
624 done = 1; // then we're done
625 res = 1; // and match
626 } else { //if it doesn't end
627 while (!done) { // until we're done
|
628 karl 1.36 if (_StringMatch(str, pat, nocase)) { // we recurse
|
629 kumpf 1.35 done = 1; //if it recurses true
630 res = 1; // we done and match
631 } else { //it recurses false
632 if (!*str) // see if test is done
633 done = 1; // yes: we done
634 else // not done:
635 str++; // keep testing
636 } // end test on recursive call
637 } // end looping on recursive calls
638 } // end logic when pattern is ambiguous
639 } else { //pattern not ambiguus
640 if (*pat == '?') { //pattern is 'any'
641 pat++, str++; // so move along
642 } else if (*pat == '[') { //see if it's a range
|
643 karl 1.36 pat = _matchrange(pat, *str, nocase); // and is a match
|
644 kumpf 1.35 if (!pat) { //It is not a match
645 done = 1; // we're done
|
646 kumpf 1.42 res = 0; // no match
|
647 kumpf 1.35 } else { //Range matches
648 str++, pat++; // keep going
649 }
650 } else { // only case left is individual characters
|
651 karl 1.36 if (!_Equal(*pat++, *str++, nocase)) // if they don't match
|
652 kumpf 1.35 done = 1; // bail.
653 }
654 } // end ("pattern is not ambiguous (*)" logic
655 } // end logic when pattern and string still have data
656 } // end logic when pattern still has data
657 } // end main loop
658 return res;
659 }
660
|
661 kumpf 1.39
|
662 karl 1.36 Boolean String::match(const String& str, const String& pattern)
663 {
664 return _StringMatch(
|
665 kumpf 1.55 (Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 0) != 0;
|
666 karl 1.36 }
667
668 Boolean String::matchNoCase(const String& str, const String& pattern)
669 {
670 return _StringMatch(
|
671 kumpf 1.55 (Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 1) != 0;
|
672 kumpf 1.39 }
673
674
675 ///////////////////////////////////////////////////////////////////////////////
676 //
677 // String-related functions
678 //
679 ///////////////////////////////////////////////////////////////////////////////
680
681 Boolean operator==(const String& str1, const String& str2)
682 {
683 return String::equal(str1, str2);
684 }
685
686 Boolean operator==(const String& str1, const char* str2)
687 {
688 return String::equal(str1, str2);
689 }
690
691 Boolean operator==(const char* str1, const String& str2)
692 {
693 kumpf 1.39 return String::equal(str1, str2);
694 }
695
696 Boolean operator!=(const String& str1, const String& str2)
697 {
698 return !String::equal(str1, str2);
699 }
700
|
701 kumpf 1.47 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
|
702 kumpf 1.39 {
|
703 kumpf 1.47 for (Uint32 i = 0, n = str.size(); i < n; i++)
|
704 kumpf 1.50 {
705 Uint16 code = str[i];
706
707 if (code > 0 && code <= PEGASUS_MAX_PRINTABLE_CHAR)
708 {
709 os << char(code);
710 }
711 else
712 {
713 // Print in hex format:
714 char buffer[8];
715 sprintf(buffer, "\\x%04X", code);
716 os << buffer;
717 }
718 }
|
719 kumpf 1.39
720 return os;
721 }
722
723 String operator+(const String& str1, const String& str2)
724 {
725 return String(str1).append(str2);
726 }
727
728 Boolean operator<(const String& str1, const String& str2)
729 {
|
730 kumpf 1.43 return String::compare(str1, str2) < 0;
|
731 kumpf 1.39 }
732
733 Boolean operator<=(const String& str1, const String& str2)
734 {
|
735 kumpf 1.43 return String::compare(str1, str2) <= 0;
|
736 kumpf 1.39 }
737
738 Boolean operator>(const String& str1, const String& str2)
739 {
|
740 kumpf 1.43 return String::compare(str1, str2) > 0;
|
741 kumpf 1.39 }
742
743 Boolean operator>=(const String& str1, const String& str2)
744 {
|
745 kumpf 1.43 return String::compare(str1, str2) >= 0;
|
746 kumpf 1.39 }
747
748 int CompareNoCase(const char* s1, const char* s2)
749 {
750 while (*s1 && *s2)
751 {
752 int r = tolower(*s1++) - tolower(*s2++);
753
754 if (r)
755 return r;
756 }
757
758 if (*s2)
759 return -1;
760 else if (*s1)
761 return 1;
762
763 return 0;
764 }
765
766 int EqualNoCase(const char* s1, const char* s2)
767 kumpf 1.39 {
768 return CompareNoCase(s1, s2) == 0;
|
769 karl 1.36 }
|
770 kumpf 1.35
|
771 mike 1.27 PEGASUS_NAMESPACE_END
|